V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
siwadiya
V2EX  ›  JavaScript

promise 存到变量中为什么可以防止阻塞?

  •  
  •   siwadiya · 2020-09-27 16:57:17 +08:00 · 4354 次点击
    这是一个创建于 1507 天前的主题,其中的信息可能已经有所发展或是发生改变。


    为什么将 promise 存到变量中,这三个 promise 就会同时运行,而不是阻塞后面代码的运行

    11 条回复    2020-09-28 11:01:58 +08:00
    abelmakihara
        1
    abelmakihara  
       2020-09-27 17:09:20 +08:00
    因为是 await 阻塞在那的
    第二个例子是执行完了再一起拿结果的
    noe132
        2
    noe132  
       2020-09-27 17:15:21 +08:00   ❤️ 1
    因为第一个例子等同于
    const timeoutPromise1 = timeoutPromise(3000)
    await timeoutPromise1
    const timeoutPromise2 = timeoutPromise(3000)
    await timeoutPromise2
    const timeoutPromise3 = timeoutPromise(3000)
    await timeoutPromise3

    而第二个例子因为都是等待 3 秒,所以 await timeoutPromise1 时第二个和第三个的时间也到了。
    你试试 如果时间不一样会怎么样

    const timeoutPromise1 = timeoutPromise(3000)
    const timeoutPromise2 = timeoutPromise(4000)
    const timeoutPromise3 = timeoutPromise(5000)
    await timeoutPromise1
    print('promise 1 done')
    await timeoutPromise2
    print('promise 2 done')
    await timeoutPromise3
    print('promise 3 done')
    Curtion
        3
    Curtion  
       2020-09-27 17:19:09 +08:00
    上面的例子中第一个 timeoutPromise 在 resolve 后才会继续注册第二个 timeoutPromise 微任务;而第二个例子在当前 Event Loop 中就一次性注册了三个微任务。
    wxsm
        4
    wxsm  
       2020-09-27 17:21:18 +08:00
    #2 说得很好了。
    siwadiya
        5
    siwadiya  
    OP
       2020-09-27 17:22:28 +08:00
    @abelmakihara 可以这么理解吗: 这三个 promise 是同步运行的,后面的 await 是为了将 pending 更改为 fulfilled
    abelmakihara
        6
    abelmakihara  
       2020-09-27 17:26:35 +08:00   ❤️ 1
    @siwadiya 当然不是了 是 await 在等待着状态变更的返回结果 因果反了
    他们都是'同步'运行了 3s
    所以 await 拿结果的时候非常快
    不然像#2 的那样
    await timeoutPromise2/3 的时候还是需要再各等待 1s 的
    Reapper
        7
    Reapper  
       2020-09-27 17:33:20 +08:00
    #2 已经很详细了,第一个例子中是 3s 3s 3s,第二个例子中,先执行了 3 个 promise,然后开始等待,3s 后有结果了,然后输出 输出 输出,async/await 只是一个语法糖,建议理解一下 promise 的执行过程
    yzqtdu
        8
    yzqtdu  
       2020-09-27 17:59:22 +08:00
    个人观点,这里不存在所谓的阻塞,generator 在 yield 之后阻塞了后续命令的执行吗?没有,执行流只是切换到其他栈去了,在合适的时机可以跳回 yield 之后的命令。async/await promise 这些都不阻塞执行流,要说阻塞,同步阻塞 io 或者 sleep 才是真的阻塞吧
    SoloCompany
        9
    SoloCompany  
       2020-09-27 19:18:26 +08:00 via iPhone
    如果希望去掉无意义的返回值

    可以用 await Promise.all
    Jirajine
        10
    Jirajine  
       2020-09-27 19:25:04 +08:00 via Android
    因为 js 的 promise 是 eager 的,创建时就已经被(调度)执行了。
    而 rust 这样的则是 lazy 的,你不 await 它就完全不会执行,这种情况下两者就一样了。
    libook
        11
    libook  
       2020-09-28 11:01:58 +08:00
    简单理解的话:函数后面加括号就是调用函数的语法,第一种是在 await 后调用,第二种是先调用再用 await 接收结果。所以第一种是等前一个 timeoutPromise 执行完返回结果后再调用执行下一个函数;第二种是三个函数依次开始执行,执行的过程是同时进行的,在 await 部分是等待前一个执行完返回结果后才等待下一个执行完返回结果。

    “存到变量”不是本质影响这个过程的因素,而是一种表象,本质是你的异步函数什么时候被调用的。可以去看看 Promise 的执行过程,await 一个 Promise 对象就是现在有结果就现在拿,现在没有结果就等着结果出来,结果出来拿到后再继续往下执行。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3737 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 00:15 · PVG 08:15 · LAX 16:15 · JFK 19:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.