Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 异步函数执行顺序_Javascript_Node.js - Fatal编程技术网

Javascript 异步函数执行顺序

Javascript 异步函数执行顺序,javascript,node.js,Javascript,Node.js,我有一个异步函数,其编写方式如下: 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(

我有一个异步函数,其编写方式如下:

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`)
  })
我在想最后的
。然后
应该在其他一切之后开火。但是
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`)
  });
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);
});
通过省略
返回
,您创建了一个独立于父链的完整的单独承诺链,因此这只是一场比赛,看哪一个先完成,因此它最终将取决于两个链中各种操作的速度,甚至可能不是每次运行时的相同完成顺序

仅供参考,如果你真的想要连续的行动,那么通常最好将你的链条扁平化为:

fn().then(...).then(...).then(...).then(...)
不是:

因为前者更清楚你想做什么。如果您有逻辑分支(您没有显示),那么您有时会被迫离开平面设计

展平后的代码如下所示:

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


我所见过的唯一一种正确决策的情况是在某种类型的fire and forget操作中,比如关闭一个文件,如果操作失败,您希望操作的其余部分正常进行,而不是等待完成,则无需采取其他措施。但这是一个罕见的例外,而不是规则。

正如其他人所说,技术问题在于缺少返回语句。然而,你也在使用一种不起眼的缩进方式,这使得你的意图不那么清晰,错误也更难发现

这是您的代码,其中添加了一些换行符和缩进更改。其思想是,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.query(…)。然后(…)
您没有将它们全部链接到一个连续的链中。您创建了两条平行且独立的链,所以这只是一场比赛,哪一条先完成。在第二个
pool.query()
前面添加一个
return
,事情就会改变。此外,您的索引级别错误,这使得发现问题变得更加困难。第7行的
.then(rows…
应该缩进更多,以便与第4行的
.then(rows…
齐平。您编写它的方式使它看起来像是要让这两个块作为第二个查询的一部分运行,但代码不是这样做的。使用
.then()
async/await
添加了扁平化代码的示例。