Reputation: 697
I'm trying to upload several files in parallel using node.js's async module. My code looks like:
// 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)
})
My problem: for n = the number of functions in toUpload, the results array callback contains the result from the last parallel task in the array, n times. I can't figure this out. it seems like every function should return its own callback with (null, url) to the parallel function.
also - when i try calling the self.upload function with the definitions of src and dest directly:
self.upload(fileArr[i]['path'], fileArr[i]['dest'], headers, function(err, url) {
cb(null, url)
})
i get a error saying "cannot read property 'path' of undefined". so, fileArr[i] is undefined. why does this happen? i feel like there is some weirdness with assignments and scope going on...
if it's not immediately obvious from the question (and the code), i'm pretty new to programming..
Upvotes: 0
Views: 1097
Reputation: 161457
Keep in mind, this is essentially:
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)
})
}
which may make it clearer that by the time your fn
function is called, the for loop has finished, so src
, and dest
will have their final loop value for every call to fn
.
Similarly, for self.upload(fileArr[i]['path'], fileArr[i]['dest'], ...
, by the time your function runs, the value of i === fileArr.length
because the for-loop has finished.
The easiest solution for this would be to use async.map
instead.
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)
}
)
I'm passing null
as the error because that is what you are doing in your example, but you should probably not be discarding errors since they might be important.
Upvotes: 1