使用异步功能与nodejs循环?

时间:2019-06-27 12:27:26

标签: node.js asynchronous

我必须检查foreignKey是否存在,但是无法使用异步查询功能进行循环

function checkAllFK(tables, foreignKeys) {
  let index = -1;
  for (var key in foreignKeys) {
    index++;
    QueryFunction(tables[index], key, foreignKeys[key])
    .then(result => {
    if(result == null) {
      //here, if result is null, that's mean the foreignKey doesn't exist, then, we have to stop the loop and return false;
      return false;
    }
    else if(index == (tables.length - 1)) {
      //here, that's mean we are at the end of the loop, and we doesn't break it with the previous if, that's mean all foreignKey exist, then, we return true;
      return true;
    }
  }

问题在于,在第一次迭代结束时,您退出该函数,并且返回结果仅取决于第一次迭代:如果在第一次迭代中满足if条件,则返回false;否则,返回null

即使在这里查看了许多类似的主题,我也没有找到解决问题的方法。

3 个答案:

答案 0 :(得分:2)

您的操作“将所有foreignKeys与所有tables进行比较”可以写在一行中。

function checkAllFK(tables, foreignKeys) {
  return Promise.all(tables.map(t => Promise.all(foreignKeys.map(k => QueryFunction(t, k))));
}

此函数返回一个承诺,该承诺将在所有查询完成后解决,因此您可以这样称呼

checkAllFK(tables, foreignKeys)
    .then(/* success */)
    .catch(/* error */);

但是,根据foreignKeystables的数量以及QueryFunction的复杂程度,这可能会对数据库服务器造成巨大压力。如果有10个表和1000个外键,这将尝试对数据库服务器并行运行10,000个查询。这不是一件明智的事情。

使用SQL处理这些情况。您可以决定对10,000个项目运行一个查询,而不是对每个事物运行10,000个查询。或10个查询,每个查询1000件事。显然,两者都比处理10,000个请求的数据库服务器更好。

例如,这一步返回了table_1中不存在的所有外键。

SELECT
  k.key_column
FROM
  foreign_keys k
  LEFT JOIN table_1 t ON t.key_column = k.key_column
WHERE
  t.key_column IS NULL

这取决于您在QueryFunction中所做的工作,实际的SQL需要如何显示。

您有多个表来检查同一外键的事实也令人担忧,这通常表明数据库设计不佳。

答案 1 :(得分:0)

很少有常见的入门错误。让我们从棘手的问题开始,它在异步上下文中的for循环中使用var关键字。如您所见,这只会返回10,而不返回1, 2, 3

for (var i=0; i < 10; i++) {
  setTimeout(() => console.log(i), 100);
}

在这种情况下,修复很容易-只需使用let,它的范围就与var不同,并且可以按您的预期工作。

    for (let i=0; i < 10; i++) {
      setTimeout(() => console.log(i), 100);
    }

第二个是异步上下文-for循环在您在QueryFunction返回的promise中执行异步上下文之前结束。如果您可以使用新版本的Node.js,那么async/await是您的救星,只需将函数标记为async并拥有

const result = await QueryFunction(tables[index], key, foreignKeys[key])

但是请注意-一旦在Promise / Asynchronous上下文中有了某些内容,您基本上就无法返回到同步上下文。因此,您的所有逻辑需求都必须意识到您处于异步状态。这基本上意味着所有结果都是承诺,您将需要thenawait它们。它不是bug或其他东西,它的行为,您需要依靠它。

答案 2 :(得分:0)

您可以执行类似打印控制台中的消息或写入文件的操作,可以获得视觉效果。

如果要获得结果,请使用“等待”。