2013-11-20 2 views
0

Я пытаюсь загрузить несколько файлов параллельно, используя асинхронный модуль node.js. Мой код выглядит следующим образом:node.js Функция async parallel возвращает один результат несколько раз

// fileArr is an array of objects. each object contains the attributes of the file to be uploaded - filename, path, destination path, etc. 

// toUpload is an array to which i push all the functions i want to execute with async.parallel 

    for (i=0; i<fileArr.length; i++) { 
    var src = fileArr[i]['path'] 
    var dest = fileArr[i]['dest'] 
    var fn = function(cb) { self.upload(src, dest, headers, function(err, url) { 
     cb(null, url) 
    }) 
    } 
    toUpload.push(fn) 
    } // for loop ends here 

async.parallel(toUpload, function(err, results) { 
    console.log('results: ' + results) 
}) 

Моей проблема: при п = число функций в toUpload, обратный вызов результатов массива содержит результат последней параллельной задачи в массиве, п раз. Я не могу понять это. Кажется, каждая функция должна возвращать свой собственный обратный вызов с (null, url) к параллельной функции.

также - когда я пытаюсь вызвать функцию self.upload с определениями ЦСИ и Dest непосредственно:

self.upload(fileArr[i]['path'], fileArr[i]['dest'], headers, function(err, url) { 
    cb(null, url) 
}) 

я получаю ошибку говоря «не может прочитать свойство„путь“неопределенных». поэтому fileArr [i] не определено. почему это происходит? я чувствую, что есть некоторые странности с заданиями и сфера происходит ...

, если это не сразу видно из вопроса (и код), я довольно новыми для программирования ..

ответ

1

Имейте в виду, , это, по существу:

var src, dest 
for (i=0; i<fileArr.length; i++) { 
    src = fileArr[i]['path'] 
    dest = fileArr[i]['dest'] 
    var fn = function(cb) { 
    self.upload(src, dest, headers, function(err, url) { 
     cb(null, url) 
    }) 
} 

, которые могут сделать его более ясным, что к тому времени, fn функция вызывается, цикл завершится, так src и dest будет иметь их конечное значение цикла для каждого вызова fn.

Аналогично, для self.upload(fileArr[i]['path'], fileArr[i]['dest'], ..., к моменту запуска вашей функции значение i === fileArr.length, потому что цикл for закончен.

Самое простое решение для этого было бы вместо этого использовать async.map.

async.map(
    fileArr, 
    function(file, callback){ 
    self.upload(file['src'], file['dest'], headers, function(err, url){ 
     callback(null, url); 
    }); 
    }, 
    function(err, results) { 
    console.log('results: ' + results) 
    } 
) 

Я передаю null как ошибка, потому что это то, что вы делаете в вашем примере, но вы должны, вероятно, не отбрасывая ошибок, так как они могут быть важны.

+0

ОК, это помогает, но подождите .. Я нажимаю fn в свой параллельный массив для каждой итерации цикла for. поэтому каждая функция в параллельном массиве должна иметь разные аргументы, верно? так как значения src и dest различаются каждый раз, когда я нажимаю функцию на массив? – amagumori

+0

Каждый экземпляр 'fn' - это новая функция, но она ссылается на значения во внешней области. Он не будет использовать эти значения до тех пор, пока функция не будет выполнена, и в этом случае к моменту ее выполнения значения были изменены следующей итерацией цикла. – loganfsmyth

+0

Yup! Я обновил пример, это была просто ошибка копирования/вставки. – loganfsmyth

Смежные вопросы