node js - 数组中每个项目的多任务处理

node js - multi tasking for each item in array

我正在尝试实现一种异步上传文件的方法。 我有一个过程要应用于数组的每个项目。 我正在获取每个项目的名称,调用 API 以获取有关它的附加信息,然后将其发送到文本到语音实用程序,并将生成的 wav 文件上传到 S3 实例。

我找不到异步执行此操作的方法,只能等待它们全部完成。

我可以在 serie 中完成,但是需要很多时间(30 个文件需要 12 分钟(每个文件 2mb))。

我试过用异步方式实现,大约需要5分钟(少了7分钟),但我担心问题出在网络上?

应用于每个项目的函数:

function doAll(c, lan, country, fileName, callback){
    getNews(c, lan)
    .then(function(newsResults){
        getWavFile(newsResults, lan, fileName)
        .then(function(wavResults){
            uploadToS3(country,lan,fileName)
            .then(function(s3Results){
                return callback("done");
            }, function(s3err){
                console.log('s3 error: ',s3err);
                return callback("done");
            })
        }, function(waverr){
            console.log('wav error: ',waverr);
        })
    }, function(newserr){
        console.log('news error: ',newserr);
    })
}

数组示例:

var arr = [
  { 
    _id: '5769369ba2d42fd82ca4d851',
    Name: 'Sports',
    Order: 1,
    Color: 'White',
    Description: 'ספורט',
    UpdatedDate: '2016-07-28T07:44:47.906Z',
    CreatedDate: '2016-06-21T12:44:11.468Z',
    Country: 'IL',
    Langs: [ 
      { 
        Name: 'Sports',
        IsoCode: 'en',
        Url: 'SportsJSON',
        _id: '576b93486c7a9ff025275836' 
      },
      { 
        Name: 'ספורט',
        IsoCode: 'iw',
        Url: 'HebrewSportsJSON',
        _id: '576be6ad56126ccc25852613' 
      } 
    ]
  },
  { 
    _id: '576bf4eb28176a3e5ce15afa',
    Name: 'Top Stories',
    Description: 'הכותרות',
    Color: 'ww',
    Order: 1,
    UpdatedDate: '2016-07-10T12:01:26.713Z',
    CreatedDate: '2016-06-23T14:40:43.435Z',
    Country: 'IL',
    Langs: [
      { 
        Name: 'כותרות',
        Url: 'HebrewTopStoriesJSON',
        IsoCode: 'iw',
        _id: '576bf52228176a3e5ce15afb' 
      },
      { 
        Name: 'Top Stories',
        IsoCode: 'en',
        Url: 'TopStoriesJSON',
        _id: '576bf94d28176a3e5ce15afd' 
      }
    ]
  },
  { 
    _id: '5756d5d6c4a3dfe478b16aa2',
    Description: 'Nation Channel',
    Order: 1,
    Color: 'blue',
    Code: 'Nation',
    Name: 'Nation',
    UpdatedDate: '2016-06-24T22:23:07.198Z',
    CreatedDate: '2016-06-07T14:10:30.699Z',
    Country: 'US',
    Langs: [
      { 
        Name: 'Nation',
        IsoCode: 'en',
        Url: 'NationJson',
        _id: '576db2cb28176a3e5ce15b02' 
      }
    ]
  }
]

我的异步方式:

var array = [] // see the example how array look like
var newArray= [];
console.log('start uploading files time:', new Date());
for (var i = 0; i < array.length; i++) {
    var list = array[i].Langs;
    for (var j= 0; j < list.length; j++) {
        var c = list[j];
        var lan = convertIsoCode(c.IsoCode);
        var fileName = array[i].Name + "_" + lan;
        var country = array[i].Country;
        doAll(c,lan,country,fileName, function(){
            newArray.push(array[i]);
            if (array.length == newArray.length) {
                console.log('done');
                defer.resolve('done');
            }
        })
    }

}

编辑:

我尝试用 async.eachasync.parallel 来实现,但没有成功,谁能告诉我正确的实现方法?

已删除 newArray 因为您不需要它来做任何有用的事情,它浪费 CPU 时间并且是一种可怕的跟踪已完成内容的方式。一个简单的计数器就可以解决问题。

自 2016 年起就不再使用 ES6。还添加了分号,因为您不一致地使用了它们。

此外,doAll 不是一个有意义的名称。

'use strict';

const async = require('async');

let array = [/*data*/];

console.log('START ' + (new Date()));
//Asynchronously iterate throught the array
async.each(array, (item, callback) => {
    //item is your array[i]
    async.each(item.Langs, (lang, callback) => {
        //lang is your array[i].Langs[j]
        let lan = convertIsoCode(item.IsoCode),
            fileName = item.Name + '_' + lan,
            country = item.Country;

        //Apply your functions
        getNews(c, lan).then((newsResults) => {
            getWavFile(newsResults, lan, fileName).then((wavResults) => {
                uploadToS3(country,lan,fileName).then((s3Results) => {
                    //Everything is OK, callback without error
                    callback();
                }, (s3err) => {
                    //Raise the error
                    callback(s3err);
                });
            }, (waverr) => {
                console.log('wav error: ',waverr);
                //Raise the error
                callback(waverr);
            });
        }, (newserr) => {
            console.log('news error: ',newserr);
            //Raise the error
            callback(newserr);
        });
    }, (error) => {
        callback(error);
    });
}, (error) => {
    //If a error was raised, everything pending will be aborted and the error will be displayed
    if(error) {
        console.log(error);
    //Else, just report it did fine
    } else {
        console.log('OK');
    }
});