小试ES6:异步编程之Generator
来源:互联网 发布:淘宝有卖二手丝袜吗 编辑:程序博客网 时间:2024/06/09 11:30
- Generator
- yield 和 next
- 异步编程方案
- 异步操作执行链
Generator
生成器是es6原生提供的异步编程方案,其语法行为和传统函数完全不同,阮大的《ECMAScript 6 入门》一书中对生成器有比较详尽的介绍,可以参考,还有一些其他的文章比如:
- 《ECMAScript 6 入门:generator》
- 深入浅出ES6(三):生成器 Generators
- 深入浅出ES6(十一):生成器 Generators,续篇
本文主要是通过一些代码示例来记录和总结生成器的用法。
yield 和 next
yield
和next
在生成器中扮演着非常重要的角色,前者是一个操作符,后者是生成器上的一个函数。
他们具有以下特性:
- 需要调用generator的
next
函数,生成器中的语句才开始执行; next
函数在生成器之外调用,意味着可以在生成器之外控制生成器内部的操作的执行过程;- 当生成器遇到
yield
操作符就立即执行yield
之后的语句并暂停,不敢妄言内部原理,姑且感性地比作savepoint; - 当再次调用生成器的
next
函数时,生成器从上次发生yield
的‘savepoint’继续执行,直到再次遇到yield
,或者遇到是return
或者throw
生成器就退出; next
的输入参数在上一次发生yield
的地方返回,所以第一次调用next
传入的参数没有卵用;next
的返回值是一个形如{done:false, value:x}
的对象,每次执行next
都会使生成器继续执行到下一条yield
,next
的返回值中的value
属性是紧接在这条yield
之后的语句执行之后的返回值,如果遇到return
或者再也没有yield
操作那么返回对象中done=true
,value
则是return
的返回值(没有return
时返回undefined
);
以上说了很多,先利用next的返回值特性容实现一个无限的斐波那契数列,他永远不会返回done=true
const f = function* fibonacci() { let [a, b] = [0, 1]; for (;;) { yield a; [a, b] = [b, a + b]; }}();//执行三次,得到0,1,1for (let i of Array(3).keys()) { console.log(f.next());}
接下来通过一段代码看看next和yield在传值和返回值上的情况,如下:
const iter = function* gen() { console.log(`yield ${(yield 'a' + 0)}`); console.log(`yield ${(yield 'b' + 1)}`); return 'c' + 2;}();console.log(`next:${iter.next(0).value}`); //输出 next:a0console.log(`next:${iter.next(1).value}`); //输出 yield 1 next:b1console.log(`next:${iter.next(2).value}`); //输出 yield 2 next:c2
- 第一个
next
触发生成器执行到第一个yield
,并立即执行'a' + 0 = 'a0'
,a0
作为这次next
的返回值 - 第二个带入参为1的
next
触发生成器执行到第二个yield
,此时第一个yield
返回1
,并执行到下一条yield
,立即这条yield
后面你的'b' + 1 = 'b1'
,b1
作为这次next
的返回 - 第三个next执行以此类推……
异步编程方案
在同步编程模型中,每个函数总是有序依次地执行,一般上一个函数执行的结果往往是下一个函数的入参,那么在javascript中如何让下一个异步操作等待上一个异步执行得到结果之后在执行呢?
我们已经知道next可以触发生成器执行到yield
操作处,并且生成器会在遇到yield
时立即执行后面的语句并暂停,那么如果yield
后面是一个异步操作,而异步操作获取到结果之后再调用next
不就实现了等待的效果么?
function asyncfuc(v) { setTimeout(function() { let r = v + 20; console.log(r); g.next(r); //把本次的结果传出并触发下一个yield }, 500);}let g = function* gen() { let v1 = yield asyncfuc(0); let v2 = yield asyncfuc(v1); return v2;}();g.next();
异步操作执行链
有了前文的基础我们可以实现一个用来执行多个异步操作的函数,定义一个run(...functions)
方法依次执行传入的函数,如下:
//这个方法用来模拟一个异步调用function delay(time, callback) { setTimeout(function () { callback(`slept for ${time}`); }, time);}function run(...functions) { //构造一个生成器循环执行传入的方法 var generator = function* sync(resume, functions) { let result; for (var func of functions) { result = yield func(result, resume); //前一个方法执行的结果作为下一个方法的入参 } return result; }(resume, functions); //提供一个方法用于推进生成器执行。 function resume(callbackValue) { generator.next(callbackValue); } generator.next(); //触发生成器立即执行第一个方法}//模拟异步方法调用, 斐波那契数列function d(result, resume) { delay(1000, (msg) => { let value = result; if (value) { [value.a, value.b] = [value.b, value.a + value.b]; } else { value = { a: 0, b: 1 }; } console.log(value.a); resume(value); }); return result;}run(d, d, d); //顺序执行异步方法
0 0
- 小试ES6:异步编程之Generator
- Javascript的异步编程(下)及es6之generator
- ES6 -- 异步编程神器2:Generator
- ES6 Generator Function 解救异步编程深度嵌套问题
- ES6-Generator与异步操作
- 12、ES6 之Generator
- ES6之Generator
- 用 ES6 generator & Promise 写异步代码
- es6 Generator与异步的同步书写
- 【ES6学习】— (2)异步编程Generator函数和Promise对象简介
- 学习笔记:ES6之Generator
- es6 之 Generator(一)
- es6 之 Generator(二)
- ES6之生成器(Generator)
- es6新特性之generator
- ES6--Generator
- ES6-generator
- 【es6】Generator
- 点击图片选定区域跳转到连接地
- 微服务架构的基础框架选择:Spring Cloud还是Dubbo
- 微信客户端+微信公众平台+新浪云SAE+Arduino+WS100(控制LED)
- 使用videoview播放视频
- Leetcode--3Sum
- 小试ES6:异步编程之Generator
- .h .lib .dll文件,静态链接库与动态链接库,静态调用与动态调用
- Linux中如何读写硬盘上指定物理扇区
- 陶哲轩实分析 6.3 节习题试解
- 迷宫问题
- mybatis批量更新 使用动态表和字段
- 文件输入/出字节流、文件缓冲输入/出字节流、文件输入/出字符流、文件缓冲输入/出字符流复制文件
- 适合编程基础入门学习网站大全
- JavaScript hasOwnProperty() 函数详解