在 for 循环内的 promise 中表达 js 死锁
Express js deadlock in promise inside for loop
我有一个带有 node.js
和 expressjs
的应用程序,现在我在尝试向数据库中插入多条记录时遇到了问题。
我有一个包含 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);
})
我有一个带有 node.js
和 expressjs
的应用程序,现在我在尝试向数据库中插入多条记录时遇到了问题。
我有一个包含 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);
})