Node.js/Javascript - 嵌套承诺和 for 循环 when.js
Node.js/Javascript - nested promises and for loop with when.js
我目前正在努力处理 promise 的控制流(promise 新手!)。
我调用 Redis,其中 returns 一个数组对象。然后我遍历每个结果并回调到 Redis 以获取一个值并希望将它们填充到最终对象 out
.
从未填充 out 对象,我猜是因为 forEach 尚未完成:
(注意 Redis 客户端库 returns 默认基于 when.js 的承诺)
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));
如何保证forEach循环完成?
我读过很多类似的帖子(我知道这是重复的)但是无法理解为什么内部 done() 方法不包含完整的 out
obj。
我想我需要将 forEach 本身包装在一个 promise 中?欣赏任何方向。
更新 1:非常感谢@David_Aurelio。我现在需要用键和值填充 out
。这是我的尝试:
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); });
里面的console.log打印出正确的key/values
key1 val1
key2 val2
最后完成的现在打印:
[ undefined, undefined ]
forEach
循环完成,但您在 中创建的 Promise 没有。 when.js 实现Promises/A+ 规范,保证承诺回调的异步解析。这意味着,保证在当前调用堆栈完成执行后调用传递给 then()
的回调。
您需要 return 来自 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
注册回调,而是在第一个 promise 尚未解决之前立即调用 console.log(out)
。
重要的是要了解流量控制 和 承诺链传送的数据由 :
决定
- 链的组成,以及任何内部链
- 承诺聚合器,例如
when.all()
- return 语句
以下是如何使用 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] return 由 REDISCLIENT.get()
调用的承诺已成功结算时才会发生。
我目前正在努力处理 promise 的控制流(promise 新手!)。
我调用 Redis,其中 returns 一个数组对象。然后我遍历每个结果并回调到 Redis 以获取一个值并希望将它们填充到最终对象 out
.
从未填充 out 对象,我猜是因为 forEach 尚未完成:
(注意 Redis 客户端库 returns 默认基于 when.js 的承诺)
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));
如何保证forEach循环完成?
我读过很多类似的帖子(我知道这是重复的)但是无法理解为什么内部 done() 方法不包含完整的 out
obj。
我想我需要将 forEach 本身包装在一个 promise 中?欣赏任何方向。
更新 1:非常感谢@David_Aurelio。我现在需要用键和值填充 out
。这是我的尝试:
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); });
里面的console.log打印出正确的key/values
key1 val1
key2 val2
最后完成的现在打印:
[ undefined, undefined ]
forEach
循环完成,但您在 中创建的 Promise 没有。 when.js 实现Promises/A+ 规范,保证承诺回调的异步解析。这意味着,保证在当前调用堆栈完成执行后调用传递给 then()
的回调。
您需要 return 来自 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
注册回调,而是在第一个 promise 尚未解决之前立即调用 console.log(out)
。
重要的是要了解流量控制 和 承诺链传送的数据由 :
决定- 链的组成,以及任何内部链
- 承诺聚合器,例如
when.all()
- return 语句
以下是如何使用 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] return 由 REDISCLIENT.get()
调用的承诺已成功结算时才会发生。