2016-08-29 2 views
-1

Ich versuche, eine Möglichkeit zum asynchronen Hochladen von Dateien zu implementieren. Ich habe einen Prozess, den ich auf jedes Element meines Arrays anwenden möchte. Ich nehme den Namen jedes Elements, rufe eine API auf, um zusätzliche Informationen darüber zu erhalten, dann sende ich es an ein Text-zu-Sprache-Dienstprogramm und lade die resultierende Datei wav auf eine S3-Instanz hoch.Knoten js - Multitasking für jedes Element in Array

Ich kann keinen Weg finden, dies asynchron zu tun, und warten auf alle von ihnen zu beenden.

Ich kann es in der Serie tun, aber es braucht viel Zeit (12 Minuten für 30 Dateien (2 MB pro Datei)).

Ich habe versucht, einen asynchronen Weg zu implementieren, der etwa 5 Minuten dauert (7 Minuten weniger), aber ich fürchte, das Problem ist auf der Netzlinie?

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); 
    }) 
} 

Array Beispiel:

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' 
     } 
    ] 
    } 
] 

Meine asynchron:

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'); 
      } 
     }) 
    } 

} 

EDIT:

Funktion auf jedes Element anwenden

Ich habe versucht, es mit async.each und async.parallel zu tun, aber ist nicht gelungen, kann mir jemand den richtigen Weg zeigen, um es zu implementieren?

+0

Ich weiß nicht viel über Versprechungen, aber es scheint 'Promise.all' ist das, was Sie suchen. ['async.each'] (http://caolan.github.io/async/docs.html#.each) wird auch tun, was Sie brauchen. – DrakaSAN

+0

async.each was ich verstehe, ist jede Funktion, so dass Sie einige Funktionen gleichzeitig tun können, aber hier ist es auch, um ein für jedes Element gleichzeitig zu tun und warten Sie alle fertig und alles versprechen? nicht sicher, weil ich einen brauche, um auf den nächsten zu warten – Erez

+0

'async.each' unterstützt einen Callback, der aufgerufen wird, sobald jede Funktion beendet ist, oder wenn ein Fehler an den Callback in irgendeiner der Funktionen weitergegeben wird. Du kannst auch jemanden benachrichtigen, wenn du ihm mit @DrakaSAN antwortest. Ich habe deinen Post nur durch Zufall gesehen. – DrakaSAN

Antwort

1

Entfernt newArray, da Sie es für nichts Brauchbares benötigen, verschwendet es CPU-Zeit und war eine schreckliche Art zu verfolgen, was getan wurde. Ein einfacher Zähler hätte die Tricks gemacht.

Gone ES6 seit es 2016 ist. Auch Semikolon hinzugefügt, weil Sie sie inkonsistent verwendet haben.

Auch doAll ist kein aussagekräftiger Name.

'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'); 
    } 
}); 
+0

Arbeiten wie eine Magie! Danke – Erez

+0

Ich würde dir empfehlen, entweder den Code ES5 oder den Rest deines Codes in ES6 zu schreiben und Werkzeuge wie 'eslint' zu verwenden, um sicherzustellen, dass du einen konsistenten Stil hast, es wird dir helfen, dich zu verbessern und nicht verloren zu gehen Überprüfe deinen Code Monate später. – DrakaSAN

+0

ich werde vielen Dank – Erez