疯狂的技术宅

以前出于工作目的,编写和翻译了大量的技术文章,以前端为主,删掉了过时的、毫无营养的内容,留下的都是精华。


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于本站

  • 回到主站

  • 搜索

如果await 同一个 Promise 两次会怎么样?

时间: 2021-01-14 分类: 前端技术   字数: 732 字 阅读: 2分钟
标签: #Promise# #await# #异步#

先看下面这道面试题:

let counter = 0;
const increment = new Promise(resolve => {
  counter++;
  resolve();
});
await increment;
await increment;
console.log(counter); // 结果是什么?

你认为 counter 的值是什么?

什么是 promise ?这是否意味着“稍后再做”?

实际上应该把 promise 看成是一个状态机。

promise 以“pending”状态开始它的生命周期。如果你要在这个状态下查询结果,则必须排队。

根据 ECMAScript 标准文档中的描述(https://tc39.es/ecma262/),上面 Promise 构造函数会立即调用我们的执行器函数。它的 counter++ 副作用运行。不带任何参数调用resolve(),在 promise 上存储一个 undefined 结果,并将其状态提升为“fulfilled”。

第一个 await 运行。 await 等同于在你的 promise 上运行.then(onFulfilled),将 onFulfilled 设置为“前面的代码”。这项工作作为微任务进入队列。 JavaScript 以先进先出的顺序执行微任务;控制最终返回给我们的函数。

第二个 await 没有什么不一样的地方。它创建一个微任务给我 promise 的结果并提前运行代码,然后等待 JavaScript 进行调度。

副作用只在 Promise 构建期间运行过一次,所以 counter 为 1.

我们推迟了工作吗?没有。promise 是同步创建和执行的。但是我们使用了 await 来处理其他微任务。

那么应该怎样推迟工作?

const microtask = Promise.resolve()
.then(() => console.log('hello from the microtask queue'));

const macrotask = new Promise(resolve =>
  // 排队宏任务
  setTimeout(() => {
    console.log('hello from the macrotask queue');
    resolve();
  })
  // 没有解决,promise 仍处于 pending 状态
);

// 这是最先输出的; 我们成功地推迟了工作
console.log('hello from the original execution context');

// yield 调度器; 运行 .then() 并输出日志
await microtask;
// yield 调度器;  promise 的状态是 fulfilled ,所以没有日志输出
await microtask;

// yield 调度器; 执行所有微任务,然后运行宏任务并输出日志
await macrotask;
// yield 调度器; promise 已经完成,所以没有日志输出
await macrotask;

Promise 构造函数是同步运行的,但是我们不必同步调用 resolve() 。 Promise.prototype.then 也推迟了工作。

Promise 构造函数和 Promise.prototype.then 都不会重复工作。

这意味着 promise 可以用来记住异步计算。如果你用了一个 promise,而且想要稍后再次用到它的结果,应该考虑保留 promise 而不是它的结果。

标签: #Promise# #await# #异步#

标题:如果await 同一个 Promise 两次会怎么样?

链接:https://fe-tech.viewnode.com/post/202101/14/

作者:疯狂的技术宅

声明: 本博客文章除特别声明外,均采用 CC BY-NC-ND 4.0 国际许可协议( 知识共享署名-非商业性使用-禁止演绎 4.0),转载请注明出处!

DOM节点和元素之间有什么区别
为什么 Promise 比setTimeout() 更快?
  • 文章目录
  • 站点概览
疯狂的技术宅

疯狂的技术宅

退休程序员,硬件发烧友,人工智能爱好者。写写代码喝喝茶,晒晒太阳带带娃。

457 日志
8 分类
583 标签
GitHub
友情链接
  • viewnode
  • mofish
标签云
  • Javascript 172
  • Node.Js 62
  • Vue 36
  • Typescript 28
  • 实战项目 28
  • 面试 21
  • React 20
  • Css 17
  • 面试题 16
  • 教程 13
  • Promise 12
  • Chrome 9
  • Debug 9
  • 调试 9
  • 资源 9
  • Deno 8
  • Dom 8
  • 杂谈 8
  • 正则表达式 8
  • 测试 8
© 2018 - 2022 疯狂的技术宅 All Rights Reserved
Powered by - Hugo v0.99.0 / Theme by - NexT
Storage by 俺的服务器 / 冀ICP备2022010157号
0%