在redis中使用nodejsasynchronous请求进行循环
我有一个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); };
“之后”控制台日志出现在“之前”控制台日志之前,callback总是返回一个空的contactList
。 这是因为如果我理解的很好,对redis的请求是asynchronous的。 但事情是我不知道如何使它的工作。 我能怎么做 ?
你有两个主要问题。
-
你的
phoneNumber
variables不会是你想要的。 这可以通过更改为.forEach()
或.map()
迭代来解决,因为这将为当前variables创build一个本地函数作用域。 -
你已经创build了一个方法来知道什么时候完成了所有的asynchronous操作。 有很多重复的问题/答案显示如何做到这一点。 你可能想使用
Promise.all()
。
我会build议这个解决scheme,利用你已经有的承诺:
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()
遍历该已过滤的数组 - 从
.map()
callback中return db.client().get(phoneNumber)
来创build一个promise数组。 - 获取电话号码的数据后,将该数据添加到您的自定义
contactList
对象(这本质上是.map()
循环的副作用。 - 使用承诺的返回数组
Promise.all()
知道什么时候全部完成。 - 使我们build立的
contactList
对象成为返回的promise的parsing值。 - 然后,调用它只需使用返回的承诺与
.then()
来获得最终结果。 如果您已经承诺可以返回,则无需添加callback参数。
最简单的解决scheme可能是使用MGET的电话号码列表,并把callback放在'然后'部分。
你也可以把承诺放在一个数组中,并使用Promise.all()。
在某些时候,你可能希望你的函数返回一个promise,而不是callback,只是为了保持一致。
考虑重构你的NodeJS代码来使用Promise 。
蓝鸟是一个很好的select: http : //bluebirdjs.com/docs/working-with-callbacks.html
您将asynchronous代码放入for循环(同步操作)。 所以,for循环的每个迭代都不会等待db.client(...)
函数结束。
看看这个stackoverflow的答案,它解释了如何使asynchronous循环:
这里
- queue.drain上的node.jsasynchronouscallback错误
- Nodejs串联运行函数
- node.js async.js nextTick vs setImmediate
- yeoman-generator中的this.async()
- 如何使用asynchronousI / O将实时数据集写入磁盘?
- 如何在Express请求处理程序中编写非阻塞asynchronous函数
- 为什么不能stream行的JavaScript运行时处理同步的asynchronous脚本?
- nodejs中多个asynchronousmongo请求
- Node js async.series无法使用Express应用程序 – 响应发生得太快