异步函数内的代码在其后面的代码之前执行

时间:2017-12-15 17:08:02

标签: javascript asynchronous async-await

我目前正在javascript中探索async / await的概念。我知道async函数会返回一个未来应该解决的promise并且它不会阻止代码的自然执行。这里我有一个代码,我写的是测试javascript的异步执行。

console.log("1")
async function asyncFunc(){
  for(i=0;i<10000000;i++){
  }
  console.log("3")
}
asyncFunc().then(()=>{console.log('4')});
console.log("2");

我除了代码将以下列方式执行:

  

首先console.log()打印1

     

其次调用异步函数。由于异步代码是非阻塞的,因此最后一个console.log()将执行,从而在控制台中打印2。

     

之后执行async函数内的console.log()并在控制台中打印3。

     

最后,承诺将被解决,then内的console.log()将被执行并打印4。

     

如此预期的产出:1,2,3,4

     

但实际上我的输出为1,3,2,4。

为什么它表现得像这样而不是我期望的方式

2 个答案:

答案 0 :(得分:5)

该函数在完成运行之前不会返回一个promise(除非你await内有另一个promise。)

循环运行(阻塞所有内容),然后评估console.log("3"),然后返回一个promise。

调用函数继续运行(记录2)。

最后,释放事件循环并调用传递给then的函数。

将函数标记为异步不会将其中的同步代码转换为异步代码。

答案 1 :(得分:1)

这里的答案很晚,昆汀是完全正确的,但有时候绘制这些东西很有帮助。让我们看一下非常简单的DECLARE @temp TABLE (DATETIME DATETIME, DATE DATE, tr INT, sh INT, tk VARCHAR(255)) INSERT INTO @temp (DATETIME, DATE, tr, sh, tk) SELECT '2018-02-06 00:00:00', '2018-02-06', 447, 2144, '10000001' UNION ALL SELECT '2018-02-06 00:00:00', '2018-02-06', 447, 2144, ''; WITH Opt AS ( SELECT * FROM @temp t WHERE t.tk = '' AND EXISTS ( SELECT * FROM @temp x WHERE cast(x.DATETIME AS DATE) = cast(t.DATETIME AS DATE) AND x.DATE = t.DATE AND x.tr = t.tr AND x.sh = t.sh AND x.tk <> t.tk ) ) UPDATE Opt SET tk = t.tk FROM opt x INNER JOIN @temp t ON cast(x.DATETIME AS DATE) = cast(t.DATETIME AS DATE) AND x.DATE = t.DATE AND x.tr = t.tr AND x.sh = t.sh AND x.tk <> t.tk SELECT * FROM @temp 函数:

async

该功能分为两部分:

  • 同步部分:所有内容(但不包括)第一个async function foo() { console.log("a"); await something(); console.log("b"); return 42; } await(或者如果它刚刚结束)。所以在上面,那是return和对console.log("a");的调用(但不是等待其结果的位)。
  • 异步部分:首先是something
  • 之后的任何内容

如果我们用明确的承诺重写该函数,它看起来就像这样(挥手细节)

await

所以看看你的功能:

function foo() {
    console.log("a");
    return something().then(() => {
        console.log("b");
        return 42;
    });
}

...我们可以看到函数中所有的代码都位于其初始同步部分中,并且它返回的承诺将通过async function asyncFunc(){ for(i=0;i<10000000;i++){ } console.log("3") } 解析。

那么为什么 do undefined函数有同步部分?出于同样的原因,您传递到async的执行程序函数同步运行:因此它可以立即启动其工作。

假设我们想在new Promise周围做一个async包装,我们期待JSON响应:

fetch

如果没有同步部分(对async function fetchJSON(...args) { const response = fetch(...args); return response.json(); }; 的调用),它将永远不会做任何事情,它的承诺将永远无法解决。