我有一个写成这样的异步函数:
pool.query(`select id from table1`)
.then(rows=>{
pool.query(`selectQuery1`)
.then(rows=>{
return pool.query(`selectQuery2`)
})
.then(rows=>{
console.log('First')
return pool.query(`selectQuery3`)
})
})
.then(rows=>{
console.log('Second')
return pool.query(`selectQuery4`)
})
我在想最后的 .then
应该在其他一切之后触发。但是 console.log
显示
second
first
我不明白为什么会这样
最佳答案
您并没有将它们全部链接成一个顺序链。
您创建了两条平行且独立的链,因此这只是一场谁先完成的比赛。
在第二个pool.query()
前面添加一个return
,事情会变成这样:
pool.query(`select id from table1`)
.then(rows=>{
// **** add return here ****
return pool.query(`selectQuery1`)
.then(rows=>{
return pool.query(`selectQuery2`)
})
.then(rows=>{
console.log('First')
return pool.query(`selectQuery3`)
})
})
.then(rows=>{
console.log('Second')
return pool.query(`selectQuery4`)
});
通过省略 return
,您创建了一个独立于父链的完整独立的 promise 链,因此这只是一场比赛,看哪个先完成,所以它最终取决于两条链中各种操作的速度,甚至每次运行时的完成顺序可能都不相同。
仅供引用,如果您真的想要顺序操作,那么通常最好将您的链扁平化为:
fn().then(...).then(...).then(...).then(...)
不是:
fn1().then(function() {
return fn2(...).then(...).then(...)
}).then(...)
因为前者更清楚您要做什么。如果你有逻辑分支(你没有显示),那么你有时会被迫离开扁平化设计。
展平后的代码如下所示:
pool.query(`select id from table1`).then(rows=>{
return pool.query(`selectQuery1`);
}).then(rows => {
return pool.query(`selectQuery2`);
}).then(rows => {
return pool.query(`selectQuery3`);
}).then(rows => {
return pool.query(`selectQuery4`);
}).then(rows => {
console.log("done");
}).catch(err => {
console.log(err);
});
或者,使用 async/wait,它可能会更干净:
try {
let rows1 = await pool.query(`select id from table1`);
let rows2 = await pool.query(`selectQuery1`);
let rows2 = await pool.query(`selectQuery2`);
let rows3 = await pool.query(`selectQuery3`);
let rows4 = await pool.query(`selectQuery4`);
console.log("done");
} catch(e) {
console.log(err);
}
仅供引用,未能从 .then()
处理程序内部返回 promise 链几乎总是一个错误,因为无法向外界传达成功或失败。
我见过的唯一正确决定的情况是在某种即发即忘的操作中,比如可能关闭一个文件,如果操作失败,您没有什么可以做的,而您希望其余的操作正常进行而不是等待完成。但这是罕见的异常(exception),而不是规则。
关于javascript - 异步函数执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57190999/