我有一个让Promise按预期工作的问题。我需要做以下事情:
我从stdout获取文件名,将它们分成行并复制它们。复制操作完成后,我想开始其他操作,这是我的问题。
我在Promise中创建了一个复制函数,如果出现错误我会立即拒绝它,如果没有错误我在复制循环完成后解决它但由于某种原因,then()中的函数在复制操作之前执行已完成
var lines = stdout.split(/\r?\n/);
copyUpdatedFiles(lines).then(
function() {
console.log('this one should be executed after copy operation');
}
);
function copyUpdatedFiles(lines) {
return new Promise(function(resolve, reject) {
for (var i = 0; i < linesLength; i++) {
fs.copy(lines[i], target, function(err) {
if (err) {
reject();
}
});
}
resolve();
});
}
请帮忙,因为我明显遗漏了什么。
答案 0 :(得分:4)
一旦您致电resolve
,就会在启动副本之后但在完成之前调用它。你必须等到resolve
之前的最后一次回调。这意味着要跟踪您看到的数量,请参阅***
评论:
function copyUpdatedFiles(lines) {
return new Promise(function(resolve, reject) {
var callbacks = 0; // ***
for (var i = 0; i < linesLength; i++) {
fs.copy(lines[i], target, function(err) {
if (err) {
reject();
} else { // ***
if (++callbacks == lines.length) { // ***
resolve(); // ***
} // ***
} // ***
});
}
});
}
或者,有几个库承诺 - 如果NodeJS样式的回调,所以你可以使用标准的承诺组合技术,如Promise.all
。如果您正在使用其中一个,那么您只需 这个:
function copyUpdatedFiles(lines) {
return Promise.all(
// CONCEPTUAL, semantics will depend on the promise wrapper lib
lines.map(line => thePromiseWrapper(fs.copy, line, target))
);
}
旁注:您的循环条件是指代码中未定义的变量linesLength
。它应该是lines.length
。
答案 1 :(得分:0)
在for
之后,在fs.copy
之后,所有fs.copy
都已放入调用堆栈中,但是它们没有完成,您不会等待副本成功解决。
您可以在var async = require('async');
var lines = stdout.split(/\r?\n/);
copyUpdatedFiles(lines).then(
function() {
console.log('this one should be executed after copy operation');
}
);
function copyUpdatedFiles(lines) {
return new Promise(function(resolve, reject) {
async.map(lines, (line, callback) => {
fs.copy(line, target, (err) => {
callback(err);
});
},
(err) => {
if(err) {
reject();
} else {
resolve();
}
});
});
}
的回调中使用计数器,并在调用每个回调后调用resolve,或使用async。
notify => subscribe