我遇到了redis和nodejs的问题。我必须遍历电话号码列表,并检查我的redis数据库中是否存在此号码。这是我的代码:
function getContactList(contacts, callback) {
var contactList = {};
for(var i = 0; i < contacts.length; i++) {
var phoneNumber = contacts[i];
if(utils.isValidNumber(phoneNumber)) {
db.client().get(phoneNumber).then(function(reply) {
console.log("before");
contactList[phoneNumber] = reply;
});
}
}
console.log("after");
callback(contactList);
};
&#34;&#34;&#34;&#34;控制台日志出现在&#34;之前&#34;控制台日志,回调始终返回空contactList
。这是因为如果我理解的话,对redis的请求是异步的。但事情是,我不知道如何使它有效。
我该怎么办?
答案 0 :(得分:4)
您有两个主要问题。
您的phoneNumber
变量将不是您想要的变量。这可以通过更改为数组的.forEach()
或.map()
迭代来解决,因为这将为当前变量创建本地函数范围。
您已经创建了一种了解所有异步操作何时完成的方法。有很多重复的问题/答案显示如何做到这一点。您可能想要使用Promise.all()
。
我建议这个解决方案利用你已经拥有的承诺:
function getContactList(contacts) {
var contactList = {};
return Promise.all(contacts.filter(utils.isValidNumber).map(function(phoneNumber) {
return db.client().get(phoneNumber).then(function(reply) {
// build custom object
constactList[phoneNumber] = reply;
});
})).then(function() {
// make contactList be the resolve value
return contactList;
});
}
getContactList.then(function(contactList) {
// use the contactList here
}, funtion(err) {
// process errors here
});
以下是如何运作的:
contacts.filter(utils.isValidNumber)
将数组过滤为有效数字。.map()
迭代过滤后的数组return db.client().get(phoneNumber)
回调的.map()
来创建一系列承诺。contactList
对象中(这实际上是.map()
循环的副作用。Promise.all()
,以了解它们何时完成。contactList
对象成为返回的promise的解析值。.then()
的promise即可获得最终结果。当您已经拥有可以返回的承诺时,无需添加回调参数。 答案 1 :(得分:1)
最简单的解决方案可能是将MGET与电话号码列表一起使用,并将回调放入&#39;然后&#39;部分。
你也可以将promises放在数组中并使用Promise.all()。
在某些时候,你可能希望你的函数返回一个promise而不是回调,只是为了保持一致。
答案 2 :(得分:1)
考虑重构您的NodeJS代码以使用Promises。
Bluebird是一个很好的选择:http://bluebirdjs.com/docs/working-with-callbacks.html
答案 3 :(得分:0)