javascript - 异步函数执行顺序
问题描述
我有一个写成这样的异步函数:
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
我不明白为什么会这样
解决方案
您没有将它们全部链接到一个顺序链中。
您创建了两条平行且独立的链条,因此这只是一场比赛,其中一个先完成。
return
在第二个前面添加一个,pool.query()
事情会变成这样:
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()
处理程序内部返回承诺链几乎总是一个错误,因为无法将成功或失败传达给外部世界。
我见过的唯一正确决定的情况是在某种火灾和忘记操作中,例如关闭一个文件,如果操作失败并且您希望其余操作正常进行,则没有什么可做的不同,并且不等待完成。但这是罕见的例外而不是规则。
推荐阅读
- python - Django 视图 app_view.views.GetHtmlView 没有返回 HttpResponse 对象。它返回 None 而不是
- javascript - 如何在可选引号之间提取字符串?
- c# - 将 JSON Highlight 查询转换为 elasticsearch
- flutter - Flutter 单击系统托盘上的通知导航到详细信息屏幕
- android - SocketException:操作系统错误:连接超时,errno = 110,地址 = 10.0.2.2,端口 = 40026
- bitbucket - Bitbucket PyPoetry 版本控制问题
- javascript - Props 原来在 Reactjs 中是未定义的
- terminal - 使用 tmux 无需两步命令
- c - 您如何确保链接器部分不会分配闪存
- java - 在String regex java中删除逗号后的空格