手写Async await核心原理,再也不怕面试官问我Async await原理

系统运维2025-11-05 06:29:424

前言

async await 语法是手写 ES7出现的,是核心基于ES6的 promise和generator实现的。

generator函数

这里就不再赘述generator,原理原理专门的再也文章讲专门的内容。

await在等待什么

我们先看看下面这代码,不怕这是async await的最简单使用,await后面返回的面试是一个Promise对象:

async function getResult() {

await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

}

getResult()

但不知你有没有想过一个问题,为什么会等到返回的官问promise的对象的状态为非pending的时候才会继续往下执行,也就是手写resolve执行之后,才会继续执行,核心就像下面的原理原理代码一样。

async function getResult() {

await new Promise((resolve,再也 reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

console.log(2);

}

getResult()

可以看到运行结果是先打印了1,再打印2了,不怕也就是云南idc服务商面试说明在返回的promise对象没执行resolve()前,就一直在await,官问等它执行。手写然后再执行下面的程序,那这个是怎么实现的呢?

原理实现

我们看一下下面的代码,输出顺序是什么?

async function getResult() {

await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(2);

console.log(2);

}, 500);

})

await new Promise((resolve, reject) => {

setTimeout(() => {

resolve(3);

console.log(3);

}, 100);

})

}

getResult()

没错是 1,2,3.。

那用generator函数专门来实现这个效果呢?

我一开始这样来实现:

function* getResult(params) {

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(2);

console.log(2);

}, 500);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(3);

console.log(3);

}, 100);

})

}

const gen = getResult()

gen.next();

gen.next();

gen.next();

但是发现打印顺序是 3,2,1.明显不对。

这里的问题主要是三个 new Promise几乎是同一时刻执行了。才会出现这种问题,所以需要等第一个promise执行完resolve之再执行下一个,所以要这么实现。

function* getResult(params) {

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(2);

console.log(2);

}, 500);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(3);

console.log(3);

}, 100);

})

}

const gen = getResult()

gen.next().value.then(() => {

gen.next().value.then(() => {

gen.next();

});

});

可以看到这样就打印正常了。

优化

但是呢,IT技术网总不能有多少个await,就要自己写多少个嵌套吧,所以还是需要封装一个函数,显然,递归实现最简单。

function* getResult(params) {

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(2);

console.log(2);

}, 500);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(3);

console.log(3);

}, 100);

})

}

const gen = getResult()

function co(g) {

g.next().value.then(()=>{

co(g)

})

}

co(gen)

再来看看打印结果:

可以发现成功执行了,但是为什么报错了?

这是因为generator方法会返回四次,最后一次的value是undefined。

而实际上返回第三次就表示已经返回done,代表结束了,所以,我们需要判断是否是已经done了,不再让它继续递归。

所以可以改成这样:

function* getResult(params) {

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(1);

console.log(1);

}, 1000);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(2);

console.log(2);

}, 500);

})

yield new Promise((resolve, reject) => {

setTimeout(() => {

resolve(3);

console.log(3);

}, 100);

})

}

const gen = getResult()

function co(g) {

const nextObj = g.next();

if (nextObj.done) {

return;

}

nextObj.value.then(()=>{

co(g)

})

}

co(gen)

可以看到这样就实现了。

完美,这个co其实也是大名鼎鼎的co函数的简单写法。

本篇文章关于async 和 await的原理揭秘就到此为止了,再讲下去就不礼貌了。

免费信息发布网
本文地址:http://www.bzuk.cn/html/069a31399617.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

iOS11Beta1(探索iOS11Beta1带来的全面升级和创新特性)

快速便捷关闭windows 7应用程序的几种方法(图文教程)

通过修改windows 7的系统权限来达到随意修改系统文件的方法(图文

Windows7下如何安装CentOS双系统

用彩纸打造趣味电脑教程(彩纸DIY教程,让电脑知识更有趣)

windows 7、windows 8设置管理员运行程序详细图解(2种方法)

windows 7和windows 8并存时如何设置Windows7为默认启动项

如何让windows 7系统显示文件扩展名的设置步骤?

友情链接

滇ICP备2023006006号-33