【问题标题】:Asynchronous Execution Order in JavaScriptJavaScript 中的异步执行顺序
【发布时间】:2021-08-23 15:22:57
【问题描述】:

我不明白为什么后面的执行输出是1 3 4 2 6 5

Promise.resolve().then(() => console.log(2));

(async() => console.log(await 6))();

console.log(1);

(async() => await console.log(3))();

Promise.resolve().then(() => console.log(5));

console.log(4);

【问题讨论】:

标签: javascript


【解决方案1】:

这是您的代码的执行方式:

  1. Promise.resolve() 创建一个已解决的承诺,将 () => console.log(2) 放入微任务队列

    queue: [ 
       () => console.log(2)
    ]
    
  2. IIFE 在您拥有await 6 的地方执行。等待 6 类似于将其包装在 Promise.resolve(6) 中,然后等待它:await Promise.resolve(6)

    await 的操作数不是promise 时,await 创建一个原生promise 并使用操作数的值来解决该promise

    queue: [ 
       resolve(6),
       () => console.log(2)
    ]
    
  3. 1 登录控制台

    queue: [ 
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1
    
  4. 第二个 IIFE 在你有 await console.log(3) 的地方执行。这就像await undefined,因为console.log(3) 将执行,3 将登录到控制台,并等待console.log 的返回值,即undefined

    简而言之,您正在等待undefined

    queue: [ 
       resolve(undefined),
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1 3
    
  5. Promise.resolve() 创建一个已解决的承诺,将 () => console.log(5) 放入微任务队列

    queue: [ 
       () => console.log(5),
       resolve(undefined),
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1 3
    
  6. 4 登录控制台

    queue: [ 
       () => console.log(5),
       resolve(undefined),
       resolve(6),
       () => console.log(2)
    ]
    
    console output: 1 3 4
    
  7. 脚本执行结束

  8. 事件循环现在将开始处理微任务队列

  9. 2 将被登录到控制台,因为它首先排队

    queue: [ 
       () => console.log(5),
       resolve(undefined),
       resolve(6)
    ]
    
    console output: 1 3 4 2
    
  10. await 6 解析为值6,然后传递给console.log。结果6 登录到控制台

    queue: [ 
       () => console.log(5),
       resolve(undefined)
    ]
    
    console output: 1 3 4 2 6
    
  11. 作为await console.log(3) 的结果创建的承诺解析为undefined 的值

    queue: [ 
       () => console.log(5)
    ]
    
    console output: 1 3 4 2 6
    
  12. 5 登录控制台

    queue: [ ]
    
    console output: 1 3 4 2 6 5
    
  13. 完成。


注意:您的代码不应依赖于解决不同的不相关承诺的时间和顺序。

【讨论】:

  • 您演示的步骤非常完美!我认为这解决了我的问题。
【解决方案2】:

1 由于执行顺序,首先打印。 3 在代码执行时打印,因为console.log() 不是异步操作。如果你把 await 放在它前面也没关系。 由于执行顺序,再次打印了 4。

现在,执行顺序的其余部分是由于异步操作。上述3条语句执行完毕后,以异步方式打印3条语句。

【讨论】:

  • 3的await会不会阻塞下面的代码?
  • @young-trigold 不,它没有。
【解决方案3】:

这里有两个序列:1 3 42 6 5。第一个在第一个滴答时产生(在任何承诺解决之前,第二个在第二个滴答时产生(在承诺解决之后)。

(async() => await console.log(3))(); 在 await 之前将 3 写入日志,因此 3 出现在任何 promise 解析之前,并且由于语句的顺序而介于 1 和 4 之间。 (请注意,这一行中的await 解析为undefined,因为console.log 不返回任何内容。

对于序列2 6 5,所有控制台日志都出现在promise 解决之后(或者等效地,await 语句),否则它们按自然顺序排列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多