在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的。 但事情是我不知道如何使它的工作。 我能怎么做 ?

你有两个主要问题。

  1. 你的phoneNumbervariables不会是你想要的。 这可以通过更改为.forEach().map()迭代来解决,因为这将为当前variables创build一个本地函数作用域。

  2. 你已经创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 }); 

这是如何工作的:

  1. 调用contacts.filter(utils.isValidNumber)将数组筛选为只有有效的数字。
  2. 调用.map()遍历该已过滤的数组
  3. .map()callback中return db.client().get(phoneNumber)来创build一个promise数组。
  4. 获取电话号码的数据后,将该数据添加到您的自定义contactList对象(这本质上是.map()循环的副作用。
  5. 使用承诺的返回数组Promise.all()知道什么时候全部完成。
  6. 使我们build立的contactList对象成为返回的promise的parsing值。
  7. 然后,调用它只需使用返回的承诺与.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循环:

这里