博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何理解async/await
阅读量:6653 次
发布时间:2019-06-25

本文共 2482 字,大约阅读时间需要 8 分钟。

今天一朋友去大厂面试完之后回来就跟我疯狂吐槽,说问得好深,感觉回答得不太好。

其中有一题就是问:你是如何理解async函数的。

大致面试过程如下:
朋友:async函数可以结合promise用于控制异步流程,以同步的思考方式来编写异步的代码,可以提高代码的可读性。
面试官:你这只是说明了使用的方法还有它的好处,还有其他的吗?它的原理是什么?
朋友:emmm.........

当时心里就在想,大厂不亏是大厂,连语法糖都不放过,不过想想也是,一般大厂如果问到这种简单的问题,回答一般都是要牵涉到原理的,那async/await的原理到底是什么?

原理

async函数的原理其实就是generator函数结合一个自动迭代器。

这里建议先去了解一下ES6中的

我们先来看一个简单的例子:

let it = null;function* gen() {    let data = yield getData();        console.log(data);}function getData() {    return new Promise((resolve, reject) => {        setTimeout(() => {            resolve('Hello Generator');        }, 1000);    })        .then(            (data) => {                // 异步数据获取成功后,通过调用迭代器的next方法将data传入data                it.next(data);            },            ...        );}// 创建迭代器it = gen();// 启动generator迭代器,执行到第一个yiled语句it.next();复制代码

这里我们启动it.next(),generator执行到第一个yiled语句后暂停,这时候getData执行,数据异步获取后在内部通过调用it.next(data)将数据data传输到generator内部,这时generator继续执行内部的data就被赋值了'Hello Generator'并打印出来。

// 打印:Hello Generator复制代码

上面我们是通过了Promise内部去控制了Generator的执行,从而让我们能以一种同步的方式去控制异步的流程。这只是一个雏形,我们可不可以以async函数使用方式为蓝本用Generator和Promise去创建这样一种模式呢?答案是可以的,我们只需要加一个会自动迭代Generator的启动器就可以了。

首先我们用Generator模拟一下async函数,先创建两个异步操作p1和p2,用于在1s后异步获取值

let p1 = () => {    return new Promise((resolve, reject) => {        setTimeout(() => {            resolve(1);        }, 1000)    });}let p2 = () => {  return new Promise((resolve, reject) => {    setTimeout(() => {      resolve(2);    }, 1000)  });}复制代码

接着我们写一个Generator函数:

function* gen() {    let x = yield p1();    console.log(`x: ${x}`);    let y = yield p2();    console.log(`y: ${y}`);}复制代码

其实到这里已经非常像async函数了,下面是async版本

async gen() {    let x = await p1();    console.log(`x: ${x}`);    let y = await p2();    console.log(`y: ${y}`);}复制代码

现在我们就只差一个会自动迭代Generator的启动器就可以完美的模拟async函数了。下面我们来编写一个简单的run函数

function run(gen) {    let it = gen();        return Promise.resolve(it.next())        .then(            function handleNext(next) {                // 结束执行                if (next.done) return;                                // 传入Promise                return Promise.resolve(next.value)                    .then(                        (res) => {                            // 将Promise的结果输入回生成器当中,并继续执行                            handleNext(it.next(res));                        }                    )                }        )}// 将gen生成器函数传入,gen函数就会执行run(gen);// 打印:// x: 1 // y: 2复制代码

run函数执行会先执行传入的生成器得到一个迭代器,返回的yield对象如果还能继续执行则将会等到当前Promise完成后自动进行下一个迭代。

原理大致就是这样了,继续撸码了。

转载地址:http://yynto.baihongyu.com/

你可能感兴趣的文章
转 Linux调优方案,sysctl.conf的设置
查看>>
SparkSQL – 从0到1认识Catalyst(转载)
查看>>
[转]深入理解MFC中程序框架
查看>>
Delphi图像处理 -- RGB与HSL转换
查看>>
e297: write error in swap file
查看>>
XamarinAndroid组件教程RecylerView自定义适配器动画
查看>>
Node.js中环境变量process.env详解
查看>>
管理 python logging 日志使用
查看>>
vue - 实例事件
查看>>
Hibernate征途(五)之继承映射和组件映射
查看>>
桥接让XE2 DATASNAP中间层支持DELPHI低版本开发客户端
查看>>
MySQL建表规范与常见问题
查看>>
Can't connect to MySQL server on (110)
查看>>
PHP的错误机制总结
查看>>
Bullet 物理引擎 简析
查看>>
获取时间戳,以秒为单位
查看>>
ASP入门(十)-Session对象
查看>>
RESTEasy使用json返回的例子
查看>>
DNS相关配置文件
查看>>
对于Json和对象转换的学习
查看>>