Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 节点js等待函数返回以继续for循环_Node.js_For Loop - Fatal编程技术网

Node.js 节点js等待函数返回以继续for循环

Node.js 节点js等待函数返回以继续for循环,node.js,for-loop,Node.js,For Loop,我有一个for循环,它在每个步骤中调用一个函数 该函数调用API,我不知道需要多长时间才能得到响应 我需要等待函数updatePE()返回一个值,然后循环进入下一步 db.query("SELECT * FROM tb_table where active = true;", (err, result) => { if (err) {console.log('ERROR'); return; } for (const key in Object.keys(result.rows))

我有一个for循环,它在每个步骤中调用一个函数

该函数调用API,我不知道需要多长时间才能得到响应

我需要等待函数
updatePE()
返回一个值,然后循环进入下一步

 db.query("SELECT * FROM tb_table where active = true;", (err, result) => {
  if (err) {console.log('ERROR'); return; }

for (const key in Object.keys(result.rows)) {

    updatePE(result.rows[key].b,result.rows[key].s,result.rows[key].k);

}
});
如果
updatePE()
是一个同步函数,那么它将等待该函数调用的返回,如果是
async
函数,那么尝试将
wait
放在该函数前面,直到函数返回

wait updatePE()//确保updatePE()是一个异步函数

像这样

async function updatePE(param1, param2, param3){
  return new Promise((resolve, reject)=>{
    //do something and call 
    //resolve(true)
  })
}
确保只能在
async
函数中调用
wait
,因此调用方函数也必须是
async

(async function(){
 db.query("SELECT * FROM tb_table where active = true;", (err, result) => {
  if (err) {console.log('ERROR'); return; }
  for (const key in Object.keys(result.rows)) {
    await updatePE(result.rows[key].b,result.rows[key].s,result.rows[key].k);
  }
 });
})()

假设您的
update
函数是异步的(基于承诺),并且您可以使用
async/await
(至少需要节点8.x),那么您可以以一种所有更新都将并行发生的方式编写代码(从代码的角度来看,实际上NodeJS在单线程的执行队列顶部运行):

更多关于JS中的async/await的信息,请参见:

另一件值得一提的事情——您的查询代码使用回调,这在现代JS世界中被认为是相当过时的——请检查您的
db
库是否公开了Promise接口——它将大大简化您的代码,并提供一致的错误处理方式,而不会带来很多麻烦

如果您希望在现有代码中正确使用Promission,但未使用Promission兼容库,则可以使用:

  • bluebird
    库及其惊人的
    Promise.fromCallback
    promisifyAll
    。详情如下:
  • 根据以下答案,自己动手:

我强烈建议你去看看图书馆,它是一个很好的图书馆

现在让我们谈谈你的问题以及如何解决它。假设
updatePE
是您自己的函数,我会将该函数转换为承诺或向其添加回调,这样您就知道它何时完成执行

比如说

// Promise implementation
function updatePE(x, y, z) {
   return new Promise(function(resolve, reject){
       // Do your work here and when is done resolve it
       resolve();
   });
}

// Callback implementation
function update(x, y, z, callback)
{
     // Do your work here and when is done, callback
     callback()
}
现在使用异步库可以执行以下操作

// If your updatePE uses callback
async.forEach(result.rows, function(row, callback) {
     updatePE(x, y, z, function() {
        callback(null)
     });
}, function(err){
     if (err) {
        // Loop is finished with an error
     } else {
        // Loop is finished without an error
     }
});

// If your updatePE uses promise
async.forEach(result.rows, function(row, callback) {
     updatePE(x, y, z)
        .then(function(){
           callback(null)
        })
        .catch(function(err){
           callback(err)
        })
}, function(err){
     if (err) {
        // Loop is finished with an error
     } else {
        // Loop is finished without an error
     }
});

使用异步库实现。它允许您仅在启动回调后才能转到for循环的下一个迭代。像这样:

var async = require('async');
async.forEach(Object.keys(result.rows), async function(key, cb) { 
  await updatePE(result.rows[key].b,result.rows[key].s,result.rows[key].k);
  cb();
}, function(err) {
   // Here you know that the loop has completed (with err or success).
});
function updatePE(b, s, k) {
  return new Promise(function(resolve, reject) {
    // Your update code here.
    if(updateSuccessful) resolve();
    else reject();
  });
}
一定要在updatePE中返回一个承诺。像这样:

var async = require('async');
async.forEach(Object.keys(result.rows), async function(key, cb) { 
  await updatePE(result.rows[key].b,result.rows[key].s,result.rows[key].k);
  cb();
}, function(err) {
   // Here you know that the loop has completed (with err or success).
});
function updatePE(b, s, k) {
  return new Promise(function(resolve, reject) {
    // Your update code here.
    if(updateSuccessful) resolve();
    else reject();
  });
}

到目前为止,您做了哪些尝试?您是否考虑过回电或承诺作为可能的解决方案?据我所知,发电机可以很好地解决此类问题。尽管我对它们的理解还不够自信,无法提供一个简单的例子。根据良好的JS实践(解释如下:),在任何情况下,当我们只想等待多个请求时,
Promise。尽管在for循环中直接使用了
wait
,但应使用所有的
。从Rasul的问题很难判断代码是必须等待所有更新还是必须按顺序执行(在我看来,后者是一个危险的决定),但我认为
Promise.all
可能是一个更好的主意。另外,由于异步作用域在
db.query
中的代码之外,因此代码无法工作。我同意,并且我认为,由于这是一个db操作,因此执行顺序是必不可少的,尽管无法确定:P