这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

前言

async await 语法是 ES7出现的,是基于ES6的 promise和generator实现的

generator函数

在之前我专门讲个generator的使用与原理实现,大家没了解过的可以先看那个手写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了,也就是说明在返回的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();
});
});

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

特别 需要解释下。gen.next().value 就是返回的promise对象,不理解的可以看看文首介绍的那篇generator的 文章。手写generator核心原理,再也不怕面试官问我generator原理

优化

但是呢,总不能有多少个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的原理揭秘就到此为止了,再讲下去就不礼貌了。

本文转载于:

https://juejin.cn/post/7136424542238408718

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--通过手写,分析async await核心原理的更多相关文章

  1. 【面试题】手写async await核心原理,再也不怕面试官问我async await原理

    前言 async await 语法是 ES7出现的,是基于ES6的 promise和generator实现的 generator函数 在之前我专门讲个generator的使用与原理实现,大家没了解过的 ...

  2. Promise及Async/Await

      一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪 ...

  3. 异步Promise及Async/Await最完整入门攻略

    一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈, ...

  4. 异步Promise及Async/Await可能最完整入门攻略

    此文只介绍Async/Await与Promise基础知识与实际用到注意的问题,将通过很多代码实例进行说明,两个实例代码是setDelay和setDelaySecond. tips:本文系原创转自我的博 ...

  5. AsyncLocal 与 async await

    大家来看一张图 先猜猜看为什么会这样 关于async await的原理 建议查看 https://blog.csdn.net/brook_shi/article/details/50803957 这篇 ...

  6. How Javascript works (Javascript工作原理) (四) 事件循环及异步编程的出现和 5 种更好的 async/await 编程方式

    个人总结: 1.讲解了JS引擎,webAPI与event loop合作的机制. 2.setTimeout是把事件推送给Web API去处理,当时间到了之后才把setTimeout中的事件推入调用栈. ...

  7. 这一次搞懂SpringBoot核心原理(自动配置、事件驱动、Condition)

    @ 目录 前言 正文 启动原理 事件驱动 自动配置原理 Condition注解原理 总结 前言 SpringBoot是Spring的包装,通过自动配置使得SpringBoot可以做到开箱即用,上手成本 ...

  8. promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

    * promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...

  9. 进阶篇:以IL为剑,直指async/await

    接上篇:30分钟?不需要,轻松读懂IL,这篇主要从IL入手来理解async/await的工作原理. 先简单介绍下async/await,这是.net 4.5引入的语法糖,配合Task使用可以非常优雅的 ...

  10. 仿async/await(一)and Gulp:新一代前端构建利器

    NET 4.5的async/await真是个神奇的东西,巧妙异常以致我不禁对其实现充满好奇,但一直难以窥探其门径.不意间读了此篇强文<Asynchronous Programming in C# ...

随机推荐

  1. Python实现冒泡排序、选择排序、插入排序

    排序与搜索 排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法. 排序算法的稳定性 稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序.也就是如 ...

  2. angularjs国际化多语言,angular-translate教程详解,$translate.instant()为什么不生效

    壹 ❀ 引 最近项目要求支持国际化多语言,由于项目用的还是angularjs,那么首当其冲的选择了angularjs封装的I18N插件angular-translate,本文主要会从三个方向展开讨论, ...

  3. 提高Java开发生产力,我选Stream API,真香啊

    Java 8 引入的Stream API提供了一种新的数据处理方式,它以声明式.函数式的编程模型,极大地简化了对集合.数组或其他支持数据源的操作.Stream可以被看作是一系列元素的流水线.允许你高效 ...

  4. Android架构组件LiveData

    LiveData LiveData是基于观察者模式创建的,其中,LiveData是被观察者,观察者通过注册方法,监听被观察者的数据变化.LiveData在数据发生变化的时候,会通知观察者. LiveD ...

  5. Maven多模块项目版本统一管理

    如图所示,项目中定义了这样几个模块: pdd-workflow-build :定义项目版本,及全局配置 pdd-workflow-dependencies :外部依赖管理,统一管理所有用到的外部依赖的 ...

  6. Swoole从入门到入土(28)——协程[核心API]

    本节专门介绍swoole提供的协程机制中核心的API 类方法: 1) set():协程设置,设置协程相关选项. Swoole\Coroutine::set(array $options); 2) ge ...

  7. 最新最简单安装龙蜥操作系统centos8

    下载 https://openanolis.cn/download 我用的是稳定版本 Anolis OS8.2QU1 安装(vm用的15.5pro) 关键点 进去后,输入命令 ip a // 查看ip ...

  8. Flask遇到的坑及解决办法

    flask_script 在使用第三方包flask_script时,报一下错误 ModuleNotFoundError: No module named 'flask._compat' 问题时flas ...

  9. 逆向实战32——某东最新h5st4.4算法分析

    前言 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 目标网站 aHR0cHM6 ...

  10. 【Azure 应用服务】基于Azure的CI/CD工具链部署App Service

    问题描述 在中国区Azure中,App Service是否支持CI/CD工具部署呢? Windows 和Linux两个系统都是同样的方法吗? 问题解答 目前中国区Azure支持Windows 和 Li ...