Node中多file upload,强制同步callback?

我有一个表单,可以在一个<input>标记中上传多个图像。 当我使用Node访问文件系统时,似乎排队读/写文件的callback是asynchronous的。 因为我有多个文件,所以我在for循环中调用了这些调用,所以在callback命中的时候, i的值始终是array.length ,导致对象未定义。

 for (var i = 0; i < req.files.photos.length; i++) { req.fs.readFile(req.files.photos[i].path, function(err, data) { if(err) throw err; // i = req.files.photos.length here // Test is undefined when the breakpoint on this line is hit for the first time var test = req.files.photos[i]; // Both print "undefined" console.log(test.name); console.log(test.originalFileName); var newPath = __dirname + "/../public/uploads/" + req.files.photos[i].name; req.fs.writeFile(newPath, data, function (err) { if (err) throw err; console.log("it worked"); }); }); } 

您可以使用IIFE(立即调用函数expression式)在for循环的每次迭代期间捕获i的正确值:

 for (var i = 0; i < req.files.photos.length; i++) { (function(j) { req.fs.readFile(req.files.photos[j].path, function(err, data) { if(err) throw err; var test = req.files.photos[j]; console.log(test.name); console.log(test.originalFileName); var newPath = __dirname + "/../public/uploads/" + req.files.photos[j].name; req.fs.writeFile(newPath, data, function (err) { if (err) throw err; console.log("it worked"); }); }); }(i)); } 

通过立即调用这个函数, i的值将被捕获到它的当前值,并作为一个新的参考( j )存储在函数中,因为i是一个原始值。 这是范围链和closures语法的经典示例,如果您仍然遇到问题,则可以在线查看更多示例

最简单的方法实际上是切换到使用async/await与承诺。 如果你需要同时做两件事,你可以使用Promise.all。

习惯于承诺或设置asynchronous/等待,但它是100%值得的。

 import pify from 'pify'; import {readFile, writeFile} from 'fs'; const readFilePr = pify(readFile); const writeFilePr = pify(writeFile); async function copyFiles(req) { const {photos} = req.files; for (let photo of photos) { try { const image = await readFilePr(photo.path); const newPath = `${__dirname}/../public/uploads/${photo.name}`; await writeFilePr(newPath); } catch (e) { console.error("Problem copying download: ",e); } } } 

你可能需要为所有的代码设置babel来工作(假设没有任何错别字或者什么,我没有testing过)。