等待节点承诺中的循环

Wait On For Loop In Node Promise

我正在尝试 运行 使用 Q 库的一系列承诺。

合并笔记功能在数据库中创建一个新笔记,由于一些独特的限制,我必须 运行 按顺序使用这些功能。

承诺按顺序 运行 没问题,但我需要将所有 newNotes 推入 workNotes 中的数组,然后解析该数组。

我尝试的一切都在链结束之前解决了承诺。

为了澄清问题,我需要在链完成后解析 notesList,并且每个生成的 newNote 都已推送到 notesList。

workNotes(notes){
    var _this = this;
    var notesList = [];
    return new Promise(
        function(resolve,reject){
            var chain = Q.when();
            notes.forEach(function(note){
                chain = chain.then(function(newNote){
                   _this.notesList.push(newNote);
                   return _this.mergeNotes(note);
                 });
             });
            resolve(notesList)
        }          
    );
}


mergeNotes(notes){
    return new Promise(
        function(resolve,reject){
            doSomething(note)
            .then(function(newNote){
             resolve(newNote);
            })   
         }       
    );
}

mergeNotes()更改为return新承诺:

mergeNotes(notes){
    return doSomething(note);
}

您正在 return 承诺,但它与 doSomething() 承诺没有任何联系,因此它没有等待。

避免 promise anti-pattern 将现有承诺包装在新创建的承诺中。相反,只是 return 你已经拥有的承诺。

我会将您的其余代码更改为:

workNotes(notes) {
    let allNotes = [];
    return notes.reduce(function(p, note) {
        return p.then(function() {
            return mergeNotes(note);
        }).then(function(newNote) {
            allNotes.push(newNote);
        });
    }, Promise.resolve()).then(function() {
        return allNotes;
    });
}

借助 Bluebird promise 库,您可以利用 Promise.mapSeries() 按顺序处理数组和 return 解析数组,这正是您需要的:

workNotes(notes) {
    return Promise.mapSeries(notes, function(note) {
        return mergeNotes(note);
    });
}

workNotes() 编辑的承诺 return 的解析值将是一组注释。

放弃无用的 _this.(注意 this 与作用域无关!),避免 Promise constructor antipattern,交换对 push 的调用顺序和 mergeNotes,并使用 reduce 而不是 forEach 将数组折叠为单个值:

function workNotes(notes) {
    var notesList = [];
    return notes.reduce(function(chain, note) {
        return chain.then(function() {
            return mergeNotes(note);
        }).then(function(newNote){
            notesList.push(newNote);
        });
    }, Q.when()).then(function() {
        return notesList;
    });
}