【问题标题】:Returning from a for loop which has an async call从具有异步调用的 for 循环返回
【发布时间】:2017-07-21 18:28:36
【问题描述】:

我有这个函数被调用一次:

exports.validate = function(roomData, callback) {
  console.log('This only prints only once!');

  getAllRooms(function(rooms) {
    if (rooms.length === 0) {
      callback(true);
      return;
    }

    for (let i = 0; i < rooms.length; i++) {
      let key = "roomAdmin:" + rooms[i].roomName;

      redis.hgetall(key, function() {
        let newUrl = roomData.url.toLowerCase();
        let existingUrl = rooms[i].url.toLowerCase();
        let newRoomName = roomData.roomName.toLowerCase();
        let existingRoomName = rooms[i].roomName.toLowerCase();

        if (newUrl === existingUrl || newRoomName === existingRoomName) {
          console.log('This prints');
          callback(false);
          return;
        }
        if (i === rooms.length - 1) {
          console.log('But this prints also?');
          callback(true);
          return;
        }
      })
    }
  });
};

我正在尝试遍历一组 redis 对象并将一些字段与一些给出的新数据进行比较。如果有匹配,我想用 false 回调并返回。如果没有匹配,我想返回 true。

我可以在下面看到我的逻辑是错误的,因为 hgetall 是异步的,所以两个返回都被调用,那么我如何停止执行并在找到匹配项后立即返回?

谢谢

【问题讨论】:

  • 您的逻辑并没有完全错误,您有一个回调作为参数,因此当结果存在时代码将正确运行。但是,根本不需要返回,这不会触发必须执行的代码的执行。之后要做的所有事情都必须在回调中,而不是在validate 调用之后依次放置。一个简单的解决方案是将redis.hgetall 调用包装在一个函数中,该函数将作为附加参数icallback 存储为一个var。这样i的值就对了

标签: javascript node.js


【解决方案1】:

停止执行由 hgetall 函数负责,因此您可以使用最简单直接的解决方案 - 传递给它的数组函数,该函数调用您的本地 let-assigned 函数。找到匹配后(或发生错误),只需将本地函数替换为空。现代 ES 解释器优化器会足够快地执行代码,但不会执行额外的回调。

类似以下内容:

let cbc = function() {
    let newUrl = roomData.url.toLowerCase();
    let existingUrl = rooms[i].url.toLowerCase();
    let newRoomName = roomData.roomName.toLowerCase();
    let existingRoomName = rooms[i].roomName.toLowerCase();
    // ......
    if(found) {
        cbc = () => {};
        callback(result);
        return
    }
}    
// ......
redis.hgetall(key, (...args) => cbc(...args));

【讨论】:

  • 这里有些东西在我的脑海中响起。当没有找到任何东西并且没有发生错误时,如何调用回调?也许我错了,但这段代码不依赖于类似同步的执行吗?如果第一个实例比第二个实例需要更多时间来回答(并引发错误),那么第二个实例是否仍然存在 cbc 函数?
  • @Kaddath 你说得对,这只是建议用例的代码概念。当然,原始的cbc 函数应该监控第 n 次调用计数,并在最后一次迭代时执行错误分支回调。关于异步执行,很可能这不是问题,因为每个闭包都有它自己的实例。再一次 - 它主要回答“如何从异步回调中返回”的问题,因此实现停止调用不可控函数的回调。
猜你喜欢
  • 2011-11-08
  • 1970-01-01
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 1970-01-01
相关资源
最近更新 更多