ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JavaScript – 用 Generator 运行异步函数 & await async

2022-05-22 17:31:16  阅读:230  来源: 互联网

标签:JavaScript Generator Iterator await Promise promise 函数


前言

上一篇 JavaScript – Promise 介绍了如何用 JS 编写可读性高的异步函数. 但其实呢, Promise 还不是最好的.

在 es6 之前, Promise 比起回调地狱是好了很多, 但是还不够美. 

一堆的 .then 和回调函数. 还不够美. 于是就有了用了 es6 的新特性 Generator 来优化 Promise 的写法. 要读懂这篇, 请先看 JavaScript – Promise 和 JavaScript – Generator Function.

 

参考

阮一峰 – Generator 函数的异步应用

 

最终画面

 

除去了一堆的 .then 回调.

Generator 看上去和同步代码差不多. 只是多了一些 yield 而已. 完美.

 

原理

Generator 的内容是 "代码块", 每一个 yield 就是一个切分.

调用 Generator 会得到 Iterator. 通过 Iterator.next 分段执行 Generator 内的代码, 这整套就是 Generator 的玩法.

上面的 myAsync Generator 函数, 把每一个异步函数切分成一个代码块.

当 Iterator.next 的时候就会得到一个 Promise. 然后由外部去执行, 等待 callback.

callback 的时候就接着下一个 .next 把 promise 返回值再交回给 Generator 函数内. 通过这样一种反向控制. 就把异步编程写成同步了.

是不是很聪明? 

上面我们只写了 Generator 函数, 它还不完整, 因为没有 Iterator 它是不会跑的. 而如上所说 Iterator 执行时还要处理 promise .then 回调等等, 代码可不少.

但不用担心, 一样逻辑时一样的, 只要写一次就 ok 了.

 

自执行 Iterator

上面只定义了 Generator 还需要一个执行

const iterator = myAsync();
const recursiveNext = () => {
  const { value: promise, done } = iterator.next();
  if (!done) {
    promise!.then(() => {
      recursiveNext();
    });
  }
};
recursiveNext();

Generator 负责 yield 返回 promise. Iterator 负责 .then 注册回调. 回调的时候继续 .next 

思路和实现大概就是上面这样. .next 还可以传入 promise resolve 的值哦.

当然, 真正的自执行比这个复杂许多. 可以看上面阮一峰的教程. 里面讲的很详细了.

 

await async (es2017)

搞明白了 Generator 运行异步函数的概念. 了解 await async 就简单多了.

它们就是 Generator 的语法糖而已.

async function myAsync() {
  await delayAsync(3000);
  console.log('a');

  await delayAsync(2000);
  console.log('b');

  await delayAsync(1000);
  console.log('c');
}

(async () => {
  await myAsync();
})();

async 就是 Generator 函数. 它里面的 yield 则换成了 await

await 就是执行自执行 Iterator (游览器 / Node.js 都封装了这个函数)

规则还是一样的. yield 必须返回 promise, await 也必须是一个 promise.

因为自执行 Iterator 负责等待和调用 callback, 所以它和 Generator 需要有一个共识的接口.

Promise 很适合作为这个共识接口. 但它也不是唯一的. 只要是可以把 callback 切分出来让另一方调用就可以作为共识的接口了.

比如 Thunk 函数

readFile 经过 Thunk 后, Iterator 就可以调用它, 然后控制 callback 了.

Thunk 和 Promise 都做到了把 callback 独立出来, 所以都可以满足自执行 Generator 的条件. 但现在大家应该都是统一用 Promise 了.

 

执行同步或异步函数

参考: 阮一峰 – Promise.try()

如果有一个函数, 你不清楚它是同步的还是异步的. 你该怎么去调用它呢? 

答案是 wrap 起来.

const fn = () => {};
(async () => {
  await (async () => fn())();
})();

因为 async 函数允许返回普通值和 promise 对象.

ECMA 有一个最新的提案叫 Promise.try, 做的事情就是 wrap 一个函数, 让它变成 promise, 就像上面那样.

但目前还不可以用.

 

标签:JavaScript,Generator,Iterator,await,Promise,promise,函数
来源: https://www.cnblogs.com/keatkeat/p/16298404.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有