我正在尝试在 Node.js 中编写类似“robocopy /mir”的函数,但我似乎无法理解如何按顺序正确执行多个异步函数。
一些背景:
- 该脚本在 Windows 上运行,因此,我需要找到一些方法来复制文件,同时保留修改时间并接收进度通知。
- 为了解决这个问题,我继续在 .NET 中编写了我的复制函数(使用 Edge.js 调用它)——这个复制函数只是回调一个节点函数来报告文件复制进度。这件作品完美无缺。
要按顺序复制文件,我的第一个想法是执行以下操作:
Object.keys(filesToCopy).forEach(function(key) {
var deferred = q.defer();
var payload = {
sourcePath: key,
destPath: filesToCopy[key],
progressCallback: progressCallback
};
console.log('Copying %s...', sourcePath);
// Edge.js called here
copyFile(payload, deferred.makeNodeResolver());
deferred.promise.then(function(result) {
console.log('%s complete.', result);
}, function(err) {
console.error('Error: ', err.message);
});
promises.push(deferred.promise);
});
不幸的是,这(如预期的那样)在调用 .NET 函数后立即开始复制每个文件,因此,我会立即收到所有文件的进度通知,并提供如下输出:
1%
2%
1%
2%
3%
3%
似乎我需要一种方法来排队要完成的工作,然后再一次将其全部启动,每个项目在下一个继续之前完成。当所有项目都完成后,我需要得到通知。解决方案似乎很简单,但由于我尝试的每个角度都伴随着另一个问题,所以我仍然无法理解。任何帮助将不胜感激,谢谢!
编辑: 正如我在评论中所述,Bergi 提供的答案是使用一个函数,该函数实际上返回了一个承诺,而我的 Edge.js 函数没有。我能够首先通过使用数组而不是对象来解决我的问题filesToCopy
,然后执行以下操作:
return filesToCopy.reduce(function(prev, curr) {
return prev.then(function() {
var deferred = q.defer();
copyFile(curr, function(err, result) {
deferred.resolve(result);
console.log('Completed %s', result);
});
return deferred.promise;
})
}, q());
这可能不是最好的方法,但它适用于我的用途。