javascript - 在调用异步函数时通过数组同步循环

标签 javascript node.js

我的问题:我有一个包含用户的数组和一个 user_hash,需要找到匹配的用户。我提出了以下解决方案:

//results is the array user objects
//safety_first.getUserHash is a function that calculates a user_hash, it retrieves the user-record based on the id and then combines values of some fields and a key and turns this into a hash.
if (results.length > 0)
    {
      var i = 0;
      function checkUserhash(user_id, user_hash, callback) {
        safety_first.getUserHash(user_id, function(check_user_hash) {
          if (user_hash == check_user_hash)
          {
            callback(user_id);
          }
          else
          {
            if ((i+1) < results.length)
            {
              i++;
              checkUserhash(results[i].id, user_hash, callback);
            }
            else
            {
              callback(false);
            }
          }
        });
      }

      checkUserhash(results[i].id, user_hash, function(user_id) {
        if (user_id)
        {
          console.log("MATCH: "+user_id);
        }
        else
        {
          console.log("NO MATCH");
        }
      });


    }

我首先尝试在 for 循环中执行此操作,但由于它异步调用 checkUserhash,因此在找到匹配项时我无法中断循环。

我正在寻找其他可能的解决方案,请分享您的想法。

问候,彼得

最佳答案

您可以 map在您的用户数组上创建一个 promise 数组。使用 Promise.all等待这些 promise 解决,然后迭代响应以检查哈希是否与 ID 匹配。

在此示例中,我使用了 async/await .我还模拟了一个散列函数例程,因此您可以看到它的运行情况。只需将解析从“id”更改为“id + 1”,然后重新运行演示即可看到 Match 变为 No match

希望这是一些用处。

const safety_first = {
  getUserHash(id) {
    return new Promise(resolve => {
      setTimeout(() => resolve(id), 1000);
    });
  }
}

async function checkUserHashes(userList, promises) {
  try {

    // await the promises to all resolve
    // `Promise.all` preserves the order...
    const res = await Promise.all(promises);

    // ...which makes it useful if you need to check the returned
    // results against the promise-producing array
    userList.forEach(({ id }, i) => {
      if (id === res[i]) console.log(`${id}|${res[i]} - Match`);
      if (id !== res[i]) console.log(`${id}|${res[i]} - No match`);
    });

  } catch (e) {
    console.log(e);
  }
};

const userList = [{ id: 1, userHash: 1 }, { id: 2, userHash: 2 }];

// `map` over the fields and return a
// validation promise for each
const promises = userList.map(({ id }) => {
  return safety_first.getUserHash(id);
});

// Pass in the original userList, and the generated promises
checkUserHashes(userList, promises);

更新:如果您想在找到匹配项时跳出循环,那会更容易一些:

const safety_first = {
  getUserHash(id) {
    return new Promise(resolve => {

      // This will match the second object (index 1)
      setTimeout(() => resolve(id === 1 ? id: id + 1), 1000);
    });
  }
}

async function checkUserHashes(userList) {

  // iterate over the array of objects
  for (let [index, obj] of userList.entries()) {

    // await for that one hash check
    const res = await safety_first.getUserHash(obj.id);

    // if it matches return the id
    if (obj.id === res) return obj;
  }

  // otherwise return null if there are no matches
  return null;
}

const userList = [{ id: 0, userHash: 1 }, { id: 1, userHash: 2 }];

(async () => {
  const id = await checkUserHashes(userList);
  console.log(id);
})();

关于javascript - 在调用异步函数时通过数组同步循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54346213/

相关文章:

javascript - WordPress 强制脚本在插件之后加载

javascript - 使用 jQuery/Javascript 打开“保存图像”对话框?

javascript - 克隆 DOM 节点列表和访问成员未定义

node.js - 如何将顶级异步等待与 typescript 一起使用?

javascript - Chrome 和 Firefox 中的 WebSocket 在一分钟不活动后断开连接

node.js - AWS Lambdas 的本地开发服务器

mysql - AWS Lambda - MySQL 缓存

javascript - 确定用户滚动与单击动画功能

javascript - GraphQL:错误:必须提供文档

JSON.stringify 与序列化