简体   繁体   English

等待节点承诺中的循环

[英]Wait On For Loop In Node Promise

I'm trying to run a sequence of promises using the Q library. 我正在尝试使用Q库运行一系列的Promise。

The merge notes function creates a new note in the database and I have to run the functions in order due to some unique constraints. 合并注释功能会在数据库中创建一个新注释,由于某些独特的限制,我必须按顺序运行这些功能。

The promises are running in sequence no problem, but I need to push all of the newNotes into an array in workNotes and then resolve that array. Promise按顺序运行没有问题,但是我需要将所有newNotes推送到workNotes中的数组中,然后解析该数组。

Everything I have tried resolves the promise before the chain is over. 我尝试过的一切都可以在链条结束之前解决诺言。

To clarify the problem, I need to resolve notesList after the chain has completed and every resulting newNote has been pushed to notesList. 为了澄清这个问题,我需要在链完成并将每个结果newNote推送到notesList之后解决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);
            })   
         }       
    );
}

Change mergeNotes() to return the new promise: 更改mergeNotes()以返回新的mergeNotes()

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

You were returning a promise, but it was not connected in any way to the doSomething() promise and thus it didn't wait for that. 您正在返回一个诺言,但是它与doSomething()诺言没有任何联系,因此它没有等待。

Avoid the promise anti-pattern of wrapping an existing promise in a newly created promise. 避免使用将现有承诺包装在新创建的承诺中的承诺反模式 Instead, just return the promise you already have. 相反,只需返回您已经拥有的承诺即可。

I'd change the rest of your code to this: 我将其余代码更改为此:

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;
    });
}

With the Bluebird promise library, you could take advantage of Promise.mapSeries() which processes an array in sequence and returns a resolved array which is exactly what you need: 借助Bluebird Promise.mapSeries()库,您可以利用Promise.mapSeries()来按顺序处理数组并返回恰好需要的已解析数组:

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

The resolved value of the promise returned by workNotes() will be an array of notes. workNotes()返回的workNotes()的解析值将是一个注释数组。

Drop the useless _this. 删除无用的_this. (notice that this is not about scope!), avoid the Promise constructor antipattern , swap the order of calls to push and mergeNotes , and use reduce instead of forEach to fold an array to a single value: (请注意, this与范围无关!),避免使用Promise构造函数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;
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM