嵌套的承诺 [英] Nested Promises

查看:60
本文介绍了嵌套的承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个执行一系列异步操作的函数,这些异步操作又执行其他异步操作的循环。我想知道一切都完成了。这似乎是让我的头脑缠绕在承诺上的好时机。

I have a function that does a series of asynchronous actions that in turn execute loops of other asynchronous actions. I'd like to know when everything is complete. It seemed like a great time to get my head wrapped around promises.

我在承诺前状态下的代码归结为类似的东西(希望在简化过程中我没有让这个例子变得无用):

My code in the before-promise state boils down to something like this (hopefully in the simplification process I haven't rendered the example useless):

myClass.prototype.doMaintenance = function() {
    var types = ['choreType1', 'choreType2'];

    types.forEach(function(choreType) {
        // find all chores of the type with score 0 (need to be done) 
        redisClient.zrangebyscore('chores:'+choreType, 0, 0, function(err, chores) {
            if (!err) {
                chores.foreach(function(chore) {
                    doChore(chore, function(err, result){
                        // chore complete!
                    });
                })
            }
        });
    });
}

我经历一个循环,对于循环中的每个项目,我做了一个异步数据库调用,并循环返回结果,为每个结果进行另一次异步调用。使用回调来传递完成所有杂务的通知似乎最好是丑陋的。因此,我的目标是:构建一个承诺,在所有家务活完成后解决。

I go through a loop, and for each item in the loop I make an asynchronous database call, and loop through the results returned, making another asynchronous call for each result. Using callbacks to pass notification that all chores are done seems like it would be ugly at best. Therefore my goal: construct a promise that will resolve when all the chores are done.

我面临两个困难。一个是简单地使用promise语法。我会告诉你我在下面尝试过的东西。首先,一个可能导致这个无法解决的问题:说第一个数据库查询返回一个单一的杂项。我(不知何故)把它作为整体完成所有家务承诺的一部分。现在我回去找一份下一类家务清单。如果在此期间完成第一项杂务怎么办?在添加其他杂务之前,所有家务成就的承诺将得到满足并将解决。

I'm facing two difficulties. One is simply getting the promise syntax right. I'll show you what I've tried below. First through, an issue that may render this insolvable: say that the first database query comes back with a single chore. I (somehow) put that as part of the overall "all chores done" promise. Now I go back to get a list of the next type of chore. What if in the meantime the first chore is completed? The all-chores-done promise will be satisfied, and will resolve, before the rest of the chores are added.

我正在使用 Q node.js 环境中的库。我使用 Redis 但它可能是任何异步数据源。

I'm using the Q library in a node.js environment. I use Redis but it could be any asynch data source.

myClass.prototype.doMaintenance = function() {
    var types = ['choreType1', 'choreType2'];
    var typePromises = [];

    types.forEach(function(choreType) {
        // find all chores of the type with score 0 (need to be done)
        Q.npost(redisClient, 'zrangebyscore', ['chores:'+choreType, 0, 0]).done(chores) {
            var chorePromises = [];
            chores.foreach(function(chore) {
                chorePromises.push(doChore(chore)); // doChore returns a promise
            });
            typePromises.push(Q.all(chorePromises));
        });
    });

    return Q.all(typePromises); // at this point, typePromises is empty. Bummer!
}

我一直在努力建立(还不是那里)是一个承诺是typePromises的集合,而typePromises又是chorePromises的集合。

What I've been trying to build (not quite there yet) is a promise that is a collection of typePromises, which in turn are collections of chorePromises.

我认为我需要的是一个结构,上面写着我保证尽快为你做好所有家务的承诺。这开始使我的头爆炸。任何指导(包括完全使用不同的模式)将不胜感激。

I think what I need is a structure that says "I promise to get you the all-chores-done promise as soon as it's available." This is starting to make my head explode. Any guidance (including using a different pattern entirely) would be greatly appreciated.

推荐答案

您正在构建<$ c $列表c> typePromises 异步 - 当你调用 Q.all(typePromises)时,它仍然是空的。相反,您需要立即返回数据库结果的承诺,您可以立即将其收集到列表中。如果您还不知道这些承诺的返回值是什么 - 不用担心,请使用然后来组成任务,例如获取 Q.all redis结果到达后,(chorePromises)

You are constructing the list of typePromises asynchronically - and when you call Q.all(typePromises), it is still empty. Instead, you immediately need to return a promise for the database result which you can immediately collect into the list. If you don't know yet what the return value of those promises will be - no worries, use then to compose the tasks like getting Q.all(chorePromises) after a redis result has arrived.

我还建议使用 map 而不是推送到每个循环中的数组 - 这也有助于确保承诺立即构建。

I also would propose using map instead of pushing to an array in an each loop - this also helps to make sure that the promises are constructed immediately.

myClass.prototype.doMaintenance = function() {
    var types = ['choreType1', 'choreType2'];
    var typePromises = types.map(function(choreType) {
        // find all chores of the type with score 0 (need to be done)
        return Q.npost(redisClient, 'zrangebyscore', ['chores:'+choreType, 0, 0]).then(function(chores) {
            var chorePromises = chores.map(doChore); // doChore returns a promise
            return Q.all(chorePromises);
        }); // then returns a promise
    });
    return Q.all(typePromises);
}

这篇关于嵌套的承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆