我有一个异步函数,其编写方式如下:
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
我不明白为什么会这样
答案 0 :(得分:2)
您没有将它们全部链接到一个顺序的链中。
您创建了两个平行且独立的链条,所以这只是一场比赛,它首先完成。
在第二个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
,您创建了一个独立于父链的完整独立的诺言链,因此这只是一场竞赛,看看哪一个先完成,以便最终取决于完成的速度这两个链中的各种操作,并且每次运行时的完成顺序甚至可能都不相同。
仅供参考,如果您确实想要顺序操作,那么通常最好将您的链条扁平化为:
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);
});
或者,使用异步/等待,它甚至可能更干净:
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()
处理程序内部返回承诺链几乎总是一个错误,因为无法与外界交流成功或失败的方法。
我所见过的唯一正确决策是发生火灾并忘记操作,例如关闭文件,如果操作失败,您别无所求,而您希望其余操作能够正常进行,不等待完成。但这是罕见的例外,而不是规则。
答案 1 :(得分:0)
正如其他人所述,技术问题是您缺少退货声明。但是,您还使用了非凝缩式缩进样式,这会使意图不那么清晰,并且更难以发现错误。
这是您的代码,其中添加了一些换行符和缩进更改。这个想法是,a)链式方法调用应该始终是多行的,每条链都在相同的层次上; b)使用块的箭头函数应该总是缩进一个比其存在范围高一个层次。 >
pool
.query(`select id from table1`)
.then(rows => {
// FIX: add 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`);
});
以这种方式显示时,很容易发现pool
有一种内部用法,而它前面没有return
。