使用Node.js异步请求在Redis中进行循环

发布于 2021-02-01 12:04:02

我在使用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);

};

“之后”控制台日志出现在“之前”控制台日志之前,并且回调始终返回一个empty
contactList。这是因为如果我很了解,对redis的请求是异步的。但问题是我不知道如何使它起作用。我能怎么做 ?

关注者
0
被浏览
208
1 个回答
  • 面试哥
    面试哥 2021-02-01
    为面试而生,有面试问题,就找面试哥。

    您有两个主要问题。

    1. 您的phoneNumber变量将不是您想要的变量。可以通过更改 数组的.forEach().map()迭代来解决此问题,因为这将为当前变量创建局部函数作用域。

    2. 您已经创建了一种方法来知道所有异步操作何时完成。有很多重复的问题/答案显示了如何执行此操作。您可能要使用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
    });
    

    运作方式如下:

    1. 调用contacts.filter(utils.isValidNumber)以将数组过滤为仅有效数字。
    2. 调用.map()以遍历该过滤后的数组
    3. return db.client().get(phoneNumber).map()回调创建一个promise数组。
    4. 获取电话号码的数据后,将该数据添加到您的自定义contactList对象中(这实际上是.map()循环的副作用。
    5. Promise.all()在返回的promise数组上使用,以了解它们何时完成。
    6. 使contactList我们建立的对象成为返回的Promise的resolve值。
    7. 然后,要调用它,只需使用返回的promise .then()即可获得最终结果。当您已经承诺可以返回时,无需添加回调参数。


推荐阅读
知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看