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并不完美:技术进步是无止 ...
随机推荐
- ASP.NET Core Filter与IOC的羁绊
前言 我们在使用ASP.NET Core进行服务端应用开发的时候,或多或少都会涉及到使用Filter的场景.Filter简单来说是Action的拦截器,它可以在Action执行之前或者之后对请求信息进 ...
- 3D Analyst Tools(3D Analyst 工具)
3D Analyst 工具 工具里有又细分如下分类: 注:以下代码的参数需要另行配置,不能直接执行:Python2不支持中文变量! 1.3D 要素 # Process: 3D 内部 arcpy.Ins ...
- 洛谷2619/bzoj2654 Tree(凸优化+MST)
bzoj的数据是真的水.. qwq 由于本人还有很多东西不是很理解 qwq 所以这里只写一个正确的做法. 首先,我们会发现,对于你选择白色边的数目,随着数目的上涨,斜率是单调升高的. 那么这时候我们就 ...
- C11 (GNU Dialect) -std=gnu11 和 -std=c11
C11 (GNU Dialect) -std=gnu11 和 -std=c11 C11 (GNU Dialect) -std=gnu11 和 -std=c11 用于 IntelliSense 的 C ...
- ThreadLocal部分源码分析
结构演进 早起JDK版本中,ThreadLocal内部结构是一个Map,线程为key,线程在"线程本地变量"中绑定的值为Value.每一个ThreadLocal实例拥有一个Map实 ...
- I-Base62
I - Base62 PS:一个任意进制转换的大数问题 传送门:Base62 短除法原理: 20(10进制) => 202(3进制) 20 = (2 * 3 ^ 2 + 0 * 3 ^ 1 + ...
- 【UE4 C++】 启动 / 关闭外部exe、开启虚拟键盘
启动/关闭外部exe 引擎自带 FPlatformProcess::CreateProc() FPlatformProcess::TerminateProc() windows api ShellEx ...
- Java:Iterator接口与fail-fast小记
Java:Iterator接口与fail-fast小记 对 Java 中的 Iterator接口 和 fail-fast,做一个微不足道的小小小小记 Iterator Iterator接口 Itera ...
- [no_code]OCR表格处理——功能规格说明书
项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 功能规格说明书 我们在这个课程的目标是 远程协同工作,采用最新技术开发软件 这个作业在哪个具体方面 ...
- Spring Cloud Gateway GatewayFilter的使用
Spring Cloud Gateway GatewayFilter的使用 一.GatewayFilter的作用 二.Spring Cloud Gateway内置的 GatewayFilter 1.A ...