nodejs then()函数在promise解析之前执行

时间:2016-07-15 13:14:02

标签: javascript node.js promise

我有一个让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();
    });
}

请帮忙,因为我明显遗漏了什么。

2 个答案:

答案 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