在 for 循环内的 promise 中表达 js 死锁

Express js deadlock in promise inside for loop

我有一个带有 node.jsexpressjs 的应用程序,现在我在尝试向数据库中插入多条记录时遇到了问题。

我有一个包含 4 条记录的数组,应用程序插入 3 条和最后一条 returns 我遇到了来自 SQL 的死锁错误。

我认为这个问题可能是因为 for 循环中的 promise。

接下来你有代码的简历:

 processOrder: (req, res) => {
  //Collecting data for variables
  //Promise to wait for data
  Promise.all([data]).then(function(result)
  {
    //iterate an array
    for (var i = 0; i < result[0].length; i++)
    {
      var new_record = request.query("INSERT INTO table_test (name, local, date) VALUES ('"+result[0][i].name+"', '"+result[0][i].local+"', '"+result[0][i].date+"')");

      //Promise to wait for insert
      Promise.all([ new_record]).then(function(result)
      {
        console.log("Record number "+i+" inserted");
      }).catch(function(err) {
        console.log(err);
        console.log("Erro collecting data");
     });
    }

    console.log("END");
    res.send('true');

  }).catch(function(err) {
    console.log(err);
    console.log("Erro collecting data");
  });

}

输出为:

END
Record number 1 inserted
Record number 2 inserted
Record number 3 inserted
deadlock error

"END"console.log应该是最后一个日志,而不是第一个。

我该如何解决这种情况?请向我解释我做错了什么。

谢谢

您正在您的 for 循环(您的查询)中执行异步操作。 "END" 的输出在循环之外。您正在启动 4 个 Promise,但您无处等待它们解决。所以首先打印结束,因为一旦创建了 Promise,for 循环就完成了(不是真正完成,但是 javascript 与下一个命令连续)。

您可以在 for 循环中等待 Promise 来解决这个问题。 而不是

Promise.all([ new_record]).then(function(result)

你可以使用

const result = await new_record;

因此你必须将整个函数标记为 async

我在下面重写了你的代码。

你可以试试

import { request } from "http";

processOrder: (req, res) => {
//Collecting data for variables
//Promise to wait for data

Promise.all([data])
.then(function(result){
  const requests = result[0].map(record => {
      // assume request.query returns promise
      return request.query("INSERT INTO table_test (name, local, date) VALUES ('"+record.name+"', '"+record.local+"', '"+record.date+"')");
  }) 
  Promise.all(requests)
  .then(function(result){
    console.log("END");
    res.send('true');
  })
  .catch(function(err) {
    console.log(err);
    console.log("Erro collecting data");
  });  
})
.catch(function(err) {
  console.log(err);
  console.log("Erro collecting data");
});
}  

如果你想登录"Record Number X inserted",那么 制作执行 request.query 和 console.log.

的承诺函数
function requestPromise(queryStmt, index){
    return new Promise(resolve, reject){
        request.query(queryStmt)
        .then(result => {
           console.log(`Record Number ${index} inserted`);
           resolve(result);
        })
        .catch(err){
           reject(err);
        })   
    }
}

然后像这样调用上面的函数

Promise.all([data])
.then(function(result){
   const requests = result[0].map((record, index) => {
      return requestPromise("INSERT INTO table_test (name, local, date) VALUES ('"+record.name+"', '"+record.local+"', '"+record.date+"')", index);

})