2016-08-29 7 views
-1

Я пытаюсь реализовать способ загрузки файлов асинхронно. У меня есть процесс, который я хочу применить к каждому элементу моего массива. Я беру имя каждого элемента, вызываю API для получения дополнительной информации об этом, затем отправляю его в утилиту для преобразования текста в речь и загружаю полученный файл wav в экземпляр S3.node js - многозадачность для каждого элемента массива

Я не могу найти способ сделать это асинхронно и дождаться завершения всех этих действий.

Я могу сделать это в серии, но это занимает много времени (12 минут для 30 файлов (по 2 мб каждого файла)).

Я попытался реализовать асинхронный путь, который занимает около 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'); 
      } 
     }) 
    } 

} 

EDIT:

Я пытался сделать это с async.each и async.parallel, но не удалось, может ли кто-нибудь показать мне правильный способ его реализовать?

+0

Я мало знаю о обещаниях, но кажется, что 'Promise.all' - это то, что вы ищете. ['async.each'] (http://caolan.github.io/async/docs.html#.each) также будет делать то, что вам нужно. – DrakaSAN

+0

async.each от того, что я понимаю, это каждая функция, поэтому вы можете делать несколько функций в одном и том же тиме, но здесь также нужно делать некоторые из них за каждый элемент и ждать, пока все закончится и обещают все? не уверен, что мне нужно ждать до следующего – Erez

+0

'async.each' поддерживает обратный вызов, который будет вызываться после завершения каждой функции или если в любой из функций передается ошибка. Кроме того, вы можете уведомить кого-то, когда вы ответите ему, используя @DrakaSAN, я только видел ваш пост на удачу. – DrakaSAN

ответ

1

Удалено newArray, поскольку оно вам не нужно для чего-либо полезного, оно тратило процессорное время и было ужасным способом отслеживания того, что было сделано. Простой счетчик сделал бы трюки.

Gone ES6 с 2016 года. Также добавлен полутень, потому что вы использовали их непоколебимо.

Кроме того, 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'); 
    } 
}); 
+0

Работайте как волшебство! Спасибо – Erez

+0

Я бы посоветовал вам либо переписать код ES5, либо остальную часть вашего кода в ES6, и использовать такие инструменты, как 'eslint', чтобы обеспечить вам последовательный стиль, это поможет вам улучшить себя и не потеряться, когда вы пересматривайте свои месяцы. – DrakaSAN

+0

Я буду вам очень благодарен – Erez