对于带有nodejs异步请求的redis循环

时间:2016-05-29 20:35:33

标签: node.js asynchronous redis

我遇到了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的请求是异步的。但事情是,我不知道如何使它有效。 我该怎么办?

4 个答案:

答案 0 :(得分:4)

您有两个主要问题。

  1. 您的phoneNumber变量将不是您想要的变量。这可以通过更改为数组的.forEach().map()迭代来解决,因为这将为当前变量创建本地函数范围。

  2. 您已经创建了一种了解所有异步操作何时完成的方法。有很多重复的问题/答案显示如何做到这一点。您可能想要使用Promise.all()

  3. 我建议这个解决方案利用你已经拥有的承诺:

    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. 来自return db.client().get(phoneNumber)回调的
    4. .map()来创建一系列承诺。
    5. 获取电话号码的数据后,将该数据添加到自定义contactList对象中(这实际上是.map()循环的副作用。
    6. 在返回的promises数组上使用Promise.all(),以了解它们何时完成。
    7. 使我们构建的contactList对象成为返回的promise的解析值。
    8. 然后,要调用它只需使用返回的带有.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)

您将异步代码放入for循环(同步操作)。因此,for循环的每次迭代都不等待db.client(...)函数结束。

看一下这个stackoverflow的答案,它解释了如何进行异步循环:

Here

相关问题