Node.js 在nodejs的循环中使用异步函数?

Node.js 在nodejs的循环中使用异步函数?,node.js,asynchronous,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) {

我必须检查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;如果在第一次迭代中不满足if条件,则返回null


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

常见的begginer错误很少。让我们从棘手的一个开始,它在异步上下文中的for循环中使用
var
关键字。如您所见,这将只返回
10
s,而不是
1、2、3

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

}
您可以像在控制台中打印消息或写入文件一样,获得可视化结果

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

您的操作“对照所有
表检查所有
外键
”可以写在一行中

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 */);
但是,根据
外键
表的数量以及
查询功能
的复杂程度,这可能会给数据库服务器带来巨大的压力。如果有10个表和1000个外键,这将尝试对数据库服务器并行运行10000个查询。这不是一件明智的事情

SQL是用来处理这些情况的。您可以决定为10000件事情运行一个查询,而不是为每件事情运行10000个查询。或者10个查询,每个查询1000件事情。这两种方法显然都比用10000个请求重击数据库服务器要好

例如,这将一步返回
表_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需要是什么样子


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

尝试研究异步等待和承诺。如何在QueryFunction周围包装一个承诺,以便在循环中使用等待时从异步函数调用它?首先不要在SQL表上逐个编写此类循环。这是非常低效的。SQL已经为此设置了操作,这些东西可以在一个SQL语句中找到。第三个问题是,OP最好使用一个使用联接或EXISTS操作的SQL语句,而不是从客户端逐个检查键。这确实不是一个答案,更适合作为注释。当你获得更多的声誉,你将能够添加评论…是的,非常多。至少使用
Promise.all
,如果可能,最好是单个查询。回答得好!