generator函数与async/await
理解async函数就要先理解generator函数,因为async就是Generator函数的语法糖
Generator 函数
Generator 函数是 ES6 提供的一种异步编程解决方案,可以先理解为一个状态机,封装了多个内部状态,执行Generator函数返回一个遍历器对象,通过遍历器对象,可以依次遍历 Generator 函数内部的每一个状态
语法上,Generator 函数是一个普通函数,但是有两个特征。
一是,function关键字与函数名之间有一个星号;
二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”);
function* helloGenerator() {
yield 'hello'
yield 'Generator'
return 'ending'
}
let Generator = helloGenerator()
调用Generator函数后并不执行,返回的也不是函数运行结果而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object)。
必须调用遍历器对象的next方法,使得指针移向下一个状态。
console.log(Generator.next()) // {value: 'hello', done: false}
console.log(Generator.next()) // {value: 'Generator', done: false}
console.log(Generator.next()) // {value: 'ending', done: true}
第一次调用next方法,Generator函数开始执行,直到遇到yield表达式为止。next方法返回一个对象,value属性就是当前yield表达式的值hello,done属性的值false,表示遍历还没有结束。
第二次调用next方法,Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式
继续调用next方法直到done属性值为true或者执行到return语句(如果没有return语句就执行到函数结束),表示遍历已经结束
如果再次调用next方法,此时Generator函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true。以后再调用next方法,返回的都是这个值
yield 表达式
可以理解为暂停的标志,遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。yield表达式与return语句都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次return语句,但是可以执行多次yield表达式。从另一个角度看,也可以说 Generator 生成了一系列的值,这也就是它的名称的来历(英语中,generator 这个词是“生成器”的意思)。另外需要注意,yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
next方法的参数
next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值
function* foo(x) {
let y = yield x + 1
let k = yield y + 2
yield k / 2
return k
}
let a = foo(1)
console.log(a.next()) // {value: 2, done: false}
console.log(a.next(3)) // {value: 5, done: false}
console.log(a.next(8)) // {value: 4, done: false}
console.log(a.next()) // {value: 8, done: true}
第一次运行next方法时,返回1+1的值2;第二次调用next方法,将上一次yield表达式的值设为3,y等于3,返回y + 2的值5;第三次调用next方法,将上一次yield表达式的值设为8,k等于8,返回k/2的值4
注意,由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。
next()、throw()、return()
除了next方法还有throw()、return()两个方法,这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式。
next()是将yield表达式替换成一个值。
throw()是将yield表达式替换成一个throw语句。
const g = function* (x, y) {
let result = yield x + y;
return result;
};
const gen = g(1, 2);
gen.throw(new Error('出错了')); // Uncaught Error: 出错了
// 相当于将 let result = yield x + y 替换成 let result = throw(new Error('出错了'));
return()是将yield表达式替换成一个return语句。
gen.return(2); // {value: 2, done: true}
// 相当于将 let result = yield x + y替换成 let result = return 2;
yield* 表达式
ES6提供了yield*表达式,用来在一个Generator函数里面执行另一个Generator函数。
function* foo(x) {
yield 1
yield* bar()
yield 4
}
function* bar() {
yield 2
yield 3
}
let a = foo()
console.log(a.next()) // {value: 1, done: false}
console.log(a.next()) // {value: 2, done: false}
console.log(a.next()) // {value: 3, done: false}
console.log(a.next()) // {value: 4, done: false}
console.log(a.next()) // {value: undefined, done: true}
由于yield* bar()语句得到的值,是一个遍历器,所以要用星号表示。运行结果就是使用一个遍历器,遍历了多个Generator函数,有递归的效果。
yield*后面的 Generator 函数(没有return语句时),等同于在 Generator 函数内部,部署一个for...of循环。
async/await
ES7 中引入了 async/await,async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。async 函数的实现原理,就是将 Generator函数和自动执行器,包装在一个函数里。
根据阮一峰老师的介绍,async函数就是Generator函数的语法糖,并对Generator函数进行了改进。

上面代码async函数就是将Generator函数的星号(*)替换成async,将yield替换成await,仅此而已
async函数对 Generator 函数的改进,体现在以下四点
- 内置执行器
Generator 函数的执行必须靠执行器,需要调用next方法,才能真正执行,得到最后结果。 - 更好的语义
async和await,比起星号和yield,语义更加清楚。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。 - 更广的适用性
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象) - 返回值是promise
async函数的返回值是Promise对象,比Generator函数的返回值是Iterator对象方便多了。可以用then方法指定下一步的操作。
async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
generator函数与async/await的更多相关文章
- vue 钩子函数 使用async await
示例: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <tit ...
- Generator function vs Async/Await
Generator function vs Async/Await generator async /await refs xgqfrms 2012-2020 www.cnblogs.com 发布文章 ...
- ES6 Generator vs ES6 async/await
ES6 Generator vs ES6 async/await next yield promise refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允 ...
- ES6入门十一:Generator生成器、async+await、Promisify
生成器的基本使用 生成器 + Promise async+await Promise化之Promisify工具方法 一.生成器的基本使用 在介绍生成器的使用之前,可以简单理解生成器实质上生成的就是一个 ...
- [转] Understanding JavaScript’s async await
PS:Promise的用处是异步调用,这个对象使用的时候,call then函数,传一个处理函数进去,处理异步调用后的结果 Promise<Action>这样的对象呢,异步调用后的结果是一 ...
- promise async await使用
1.Promise (名字含义:promise为承诺,表示其他手段无法改变) Promise 对象代表一个异步操作,其不受外界影响,有三种状态: Pending(进行中.未完成的) Resolved( ...
- JavaScript中的Generator函数
1. 简介 Generator函数时ES6提供的一种异步编程解决方案.Generator语法行为和普通函数完全不同,我们可以把Generator理解为一个包含了多个内部状态的状态机. 执行Genera ...
- Promise和async await详解
本文转载自Promise和async await详解 Promise 状态 pending: 初始状态, 非 fulfilled 或 rejected. fulfilled: 成功的操作. rejec ...
- Async/Await替代Promise的6个理由
译者按: Node.js的异步编程方式有效提高了应用性能:然而回调地狱却让人望而生畏,Promise让我们告别回调函数,写出更优雅的异步代码:在实践过程中,却发现Promise并不完美:技术进步是无止 ...
随机推荐
- bzoj4094 && luogu3097 最优挤奶
题目大意: 给定n个点排成一排,每个点有一个点权,有m次修改,每次改变某个点的点权并将最大点独立集计入答案,输出最终的答案 其中\(n\le 40000\ , \ m\le 50000\) QWQ说实 ...
- SpringBoot-邮件任务
邮件发送,在我们的日常开发中,也非常的多,Springboot也帮我们做了支持 邮件发送需要引入spring-boot-start-mail SpringBoot 自动配置MailSenderAuto ...
- SudokuSolver 2.0:用C++实现的数独解题程序 【一】
SudokuSolver 2.0 实现效果 H:\Read\num\Release>sudoku.exe Order please: Sudoku Solver 2.0 2021/10/2 by ...
- jsonp和cors解决跨域
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.对于JSON大家应该是很了解了吧,不是很清楚的朋友可以去json.org上了解下,简单易懂. 1.什么是跨 ...
- 【UE4 C++】 外部图片读取、Texture 保存 png
蓝图版 导入外部图片 file://E:/UE___Projects_Test/MyProjectAAA/Plugins/WXimage.jpg 导出图图片 一般导出 .hdr 文件 导出 png 设 ...
- 【c++ Prime 学习笔记】第12章 动态内存
对象的生存期: 全局对象:程序启动时创建,程序结束时销毁 局部static对象:第一次使用前创建,程序结束时销毁 局部自动对象:定义时创建,离开定义所在程序块时销毁 动态对象:生存期由程序控制,在显式 ...
- Java字符串转数字和数字转字符串
int转String有3种方式 (1)num + "" (2)String.valueOf(num) (3)Integer.toString(num) String转int有2种方 ...
- mybatis学习笔记(2)基本原理
引言在mybatis的基础知识中我们已经可以对mybatis的工作方式窥斑见豹(参考:<MyBatis----基础知识>).但是,为什么还要要学习mybatis的工作原理?因为,随着myb ...
- BUAA 软工 结对项目作业
1.相关信息 Q A 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 系统地学习软件工程开发知识,掌握相关流程和技术,提升 ...
- Qt学习-模仿Qt实现一个colorbutton
1.mycolorbutton.h #include<QToolButton> #include<QtGlobal> #include<QColor> class ...