首页 > 解决方案 > 异步函数执行顺序

问题描述

我有一个写成这样的异步函数:

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 

我不明白为什么会这样

标签: javascriptnode.js

解决方案


您没有将它们全部链接到一个顺序链中。

您创建了两条平行且独立的链条,因此这只是一场比赛,其中一个先完成。

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()处理程序内部返回承诺链几乎总是一个错误,因为无法将成功或失败传达给外部世界。

我见过的唯一正确决​​定的情况是在某种火灾和忘记操作中,例如关闭一个文件,如果操作失败并且您希望其余操作正常进行,则没有什么可做的不同,并且不等待完成。但这是罕见的例外而不是规则。


推荐阅读