在节点承诺中等待循环

时间:2017-06-01 00:17:31

标签: javascript node.js promise q

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

合并注释函数在数据库中创建一个新注释,由于一些独特的约束,我必须按顺序运行这些函数。

promises顺序运行没问题,但我需要将所有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);
            })   
         }       
    );
}

2 个答案:

答案 0 :(得分:0)

更改mergeNotes()以返回新承诺:

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

你回复了一个承诺,但它与doSomething()承诺没有任何联系,因此它没有等待。

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

我将其余代码更改为:

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()按顺序处理数组并返回一个解析数组,这正是您所需要的:

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

workNotes()返回的承诺的已解决值将是一系列备注。

答案 1 :(得分:0)

删除无用的_this.(注意this与范围无关!),避免Promise constructor antipattern,将调用顺序交换为pushmergeNotes,并使用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;
    });
}