Node.js / Javascript - 嵌套的promises和for循环使用when.js

时间:2015-07-19 22:06:07

标签: javascript node.js foreach promise when-js

我目前正在努力控制承诺的流程(承诺新手!)。

我调用Redis返回一个数组对象。然后,我遍历每个结果并回调Redis以获取值,并希望将这些值填充到最终对象plot <- ggplot(data,aes(x=x,y=x)) + geom_point()

out对象永远不会填充,因为forEach还没有完成,我猜测:

(注意Redis客户端lib返回基于when.js的promise作为默认值)

out

我如何保证forEach循环完整?

我已经阅读了很多类似的帖子(我知道这是重复的)但是却无法理解为什么内部的done()方法不包含完全完整的var out = {}; REDISCLIENT.keys("apikey:*") .then(function (replies) { replies.forEach(function (key, index) { REDISCLIENT.get(key) .then(function (value) { out[key] = value; }) .done(console.log(out)); }); }) .catch(console.log) .done(console.log(out)); obj。

我猜我需要将forEach包装在一个承诺中吗?欣赏任何方向。

更新1:非常感谢@David_Aurelio。我现在需要使用键和值填充out。这是我的尝试:

out

内部console.log打印正确的键/值

GLOBAL.REDISCLIENT.keys("apikey:*")
        .then(function (replies) {
            return when.all(replies.map(function (key, index) {
                return GLOBAL.REDISCLIENT.get(key)
                    .then(function (val) {
                        out[key] = val;
                        console.log(key, val);
                    });
            }));
        })
        .catch(console.log)
        .done(function (out) {console.log(out); });

现在最后完成打印:

key1 val1
key2 val2

2 个答案:

答案 0 :(得分:0)

forEach循环完成,但您在内创建的Promise不会。 when.js 实现Promises/A+规范,这保证promise回调的异步解析。这意味着,保证在当前调用堆栈完成执行后调用传递给then()的回调。

您需要从then - 回调中返回一个承诺,以便将内部承诺连接到外部承诺。更具体地说,你需要承诺所有内心的承诺。

最简单的方法是使用when.all

REDISCLIENT.keys("apikey:*")
  .then(function (replies) {
    return when.all(replies.map(function (key, index) {
      return REDISCLIENT.get(key);
    }));
  })
  .catch(console.log)
  .done(function (out) {console.log(out); });

在原始代码中,您也不会将回调注册到done,而是在第一个承诺解决之前立即致电console.log(out)

答案 1 :(得分:0)

了解流量控制由承诺链传达的数据非常重要,具体取决于:

  • 链的组成和任何内链
  • 承诺聚合器,例如when.all()
  • return statements

这里是如何通过out作为内部成员来实现您想要的目标。

REDISCLIENT.keys("apikey:*")
.then(function (replies) {
    var out = {}: //<<<<< initiate `out` as an inner member
    return when.all(replies.map(function (key, index) { //<<<<< here's David Aurelio's when.all(replies.map(...))
        return REDISCLIENT.get(key).then(function (value) { //<<<<< `return` here causes `.map()` to build an array of promises.
            out[key] = value;
        });
    })).then(function() { //<<<< here's an additional `.then()` chained to `when.all(...)`
        return out; //<<<<< `return` here makes the populated `out` available to the `.done()` callback below.
    });
})
.catch(console.log)
.done(function (out_) {
    console.log(out_);
});

丑陋的外围成员已经消失了!

.done()回调中,我已将成员名称更改为out_,以强调由于return out传递,当所有 [geddit] REDISCLIENT.get()次呼叫返回的承诺成功结算时,只发生