ES6 Generator使用
// generator介绍:
function* hello() {
console.log("hello world")
}
hello();//没有执行
// 直接调用hello不能像普通函数一样打印输出。
function* hello() {
console.log("hello world")
}
var h = hello();//仅仅创建了函数句柄,并没有实际执行,需要进一步调用next()
h.next();//打印出了“hello world”
function* hello() {
yield "hello";
yield "world";
return;
}
var h = hello();
h.next();//{value:'hello',done: false}
h.next();//{value: 'world', done: false}
h.next();//{value: undefined, done: true}
// 分析:上面引入了yield关键字:
// (1)创建了h对象,指向hello的句柄,
// (2)第一次调用next(),执行到"yield hello",暂缓执行,并返回了"hello"
// (3)第二次调用next(),继续上一次的执行,执行到"yield world",暂缓执行,并返回了"world"。
// (4)第三次调用next(),直接执行return,并返回done:true,表明结束。
// 经过上面的分析,yield实际就是暂缓执行的标示,每执行一次next(),相当于指针移动到下一个yield位置。
// 总结一下,Generator函数是ES6提供的一种异步编程解决方案。通过yield标识位和next()方法调用,实现函数的分段执行。
function* gen(x, y) {
let z = yield x + y;
let res = yield z * 5;
return res;
}
var g = gen(5,6);
console.log(g.next());//{value: 11, done: false};
console.log(g.next());//{value: NAN, done:false};
console.log(g.next());//{value: undefined, done: true}
// 分析:
// (1)创建了g对象,指向gen的句柄,并传入参数x=5,y=6
// (2)第一次调用next(),执行yield x+y, value值是11,后面还没有return,也没有到最后的yield,所以没退出
// (3)第二次调用next(),执行yield z*5, 为什么输出是 NAN并不是预想的55呢?因为将yield表达式的结果赋值给z之后,进行下一次next(),z的值并没有保存。
// (4)第三次调用next(),遇到return,执行结束done:false
// 分析(3),z的值没有保存,但是怎么才能达到预期的55呢?改成下面的程序段
function* gen(x, y) {
let z = yield x + y;
let res = yield z * 5;
return res;
}
var g = gen(5,6);
console.log(g.next());//{value: 11, done: false};
console.log(g.next(11));//{value: NAN, done:false};
console.log(g.next());//{value: undefined, done: true}
// 再执行第二次next()调用时,next的参数11可以作为yield中,参数11是上一次yield表达式的结果,也就是let z=yield x+y 变成了 let z=11;所以输出了正确的结果
// 我们不能每次都把计算好的结果写到参数中,所以,修改程序段如下:
function* gen(x, y) {
let z = yield x + y;
let res = yield z * 5;
return res;
}
var g = gen(5,6);
let i = g.next();//i: {value: 11, done: false};
console.log(g.next(i.value()));//{value: NAN, done:false};
console.log(g.next());//{value: undefined, done: true}
// 最终执行第二次next()调用时,value值是预期的55。
// 总结:next()函数的参数作为上一个yield表达式的结果。
function *gen() {
yield 1;
yield 2;
yield 3;
}
let g = gen();
g.next();//{value: 1, done: false}
g.next();//{value: 2, done: false}
g.return();//遇到return()函数,generat函数遍历结束,{value: undifined, done: true},yield 3表达式并没有执行
function *gen() {
yield 1;
yield 2;
yield 3;
}
let g = gen();
g.next();//{value: 1, done: false}
g.next();//{value: 2, done: false}
g.return(5);//遇到return()函数,generator函数遍历结束,其参数5作为结果的value值{value: 5, done: true},yield 3表达式并没有执行
// yield表达式是generator函数暂缓执行的标志,只能配合generator函数使用,用在普通函数中会报错。
function gen(x,y){
yield 1;
yield 2;
yield 3;
}//Uncaught SyntaxError: Unexpected number
// yield*表达式的用法:
function *foo() {
yield 'a';
yield 'b';
}
function bar() {
yield 1;
yield 2;
yield foo();
yield 3;
}
var b = bar();
console.log(b.next());//{value: 1, done: false}
console.log(b.next());//{value: 2, done: false}
console.log(b.next());//{value: "a", done: false}
console.log(b.next());//{value: "b", done: false}
console.log(b.next());//{value: 3, done: false}
console.log(b.next());//{value: undefined, done: true}
// generator函数的应用:
// generator可以模拟多线程之间的协作。
// 比如说A,B两个线程根据实际逻辑控制共同完成某个任务,A运行一段时间后,暂缓执行,交由B运行,B运行一段时间后,再交回A运行,直到运行任务完成。
// 对于JavaScript单线程来说,我们可以理解为函数间的协作,由多个函数间相互配合完成某个任务。
// Generator函数是ES6提供的一种异步编程解决方案,解决了异步编程的两大问题:
// 回调地狱和异步控流
// 回调地狱与promise有关,不做介绍了
// 异步控流是什么?异步操作之间,又可以认为成是同步的,上一个异步执行完之后,才可以执行下一个异步程序,这时候需要一个函数来控制这个异步的流程。
// 如果task1完成了再做task2,然后交上task1,再交上task2。
// 若是如下:只能通过setTimeOut的时间控制实现异步。
function task1(next) {
setTimeout(function(){
console.log("Task1 done");
},100)
}
function task2(next) {
setTimeout(function(){
console.log("Task2 done");
},200)
}
function endTask1(next) {
setTimeout(function(){
console.log("send task1");
},300)
}
function endTask2(next) {
setTimeout(function(){
console.log("send task2");
},400)
}
task1()
task2()
endTask1()
endTask2()
// 但是如果执行完每个步骤的时间相同甚至task1需要用时最多怎么办呢?
// 如下:
setTimeout(function() {
console.log("Task1 done");
setTimeout(function(){
console.log("Task2 done");
setTimeout(function(){
console.log("send task1");
// ....... 陷入了回调地狱
},500)
},500)
},500)
// 使用generat解决
function task1(next) {
setTimeout(function(){
console.log("Task1 done");
next();//完成后需要执行的下一件事
},500)
}
function task2(next) {
setTimeout(function(){
console.log("Task2 done");
next();//完成后需要执行的下一件事
},500)
}
function endTask1(next) {
setTimeout(function(){
console.log("send task1");
next();//完成后需要执行的下一件事
},500)
}
function endTask2(next) {
setTimeout(function(){
console.log("send task2");
next();//完成后需要执行的下一件事
},500)
}
function run(fn) {
let gen = fn();//fn:tack;fn(): task();
function next() {
let result = gen.next();//第一轮:执行yield task1;其中task1是个函数。所以,下面result.value是个函数。
if (result.done) {
return;
}
// 第一轮:result.value是个函数,代表了task1,参数传入next函数名,实现了在task1中调用了run中的next函数,进而进行第二轮。
result.value(next);
};
next();
}
function* task() {
yield task1;
yield task2;
yield endTask1;
yield endTask2;
}
run(task);
// 控制台每隔500ms分别输出 "Task1 done" ,"Task2 done" ,"send task1" ,"send task2"
ES6 Generator使用的更多相关文章
- es6 generator函数的异步编程
es6 generator函数,我们都知道asycn和await是generator函数的语法糖,那么genertaor怎么样才能实现asycn和await的功能呢? 1.thunk函数 将函数 ...
- ES6 Generator vs ES6 async/await
ES6 Generator vs ES6 async/await next yield promise refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允 ...
- es6 generator函数
es6 新增了Generator函数,一种异步编程的解决方案 回顾一下,es6 提供了新的遍历方法,for of ,适用于各种数据集合,统一了遍历操作,原生支持for of 集合的数据集合有.数组,字 ...
- ES6 Generator的应用场景
一.基础知识 API文档 ES6 诞生以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 Promise 对象 Generator 函数将 JavaScript 异步编程带入了一个 ...
- ES6 Generator async
Generator 函数是 ES6 提供的一种异步编程解决方案 async 函数使得异步操作变得更加方便,是 Generator 函数的语法糖. js单线程的原因是:避免DOM渲染冲突! 更新:201 ...
- ES6 Generator 学习笔记一
Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同. Generator 函数有多种理解角度.从语法上,首先可以把它理解成,Generator 函数是一个状态机 ...
- ES6 generator 基础
参考文档 harmony:generators Generator是ES6的新特性,通过yield关键字,可以让函数的执行流挂起,那么便为改变执行流程提供了可能. 创建Generator functi ...
- ES6:Generator函数(1)
Generator函数是ES6提供的一种异步编程解决方案.它会返回一个遍历器对象 function* helloWorldGenerator(){ yield “hello”; yield “worl ...
- es6 --- Generator 函数
第一部分,ES6 中的 Generator 在 ES6 出现之前,基本都是各式各样类似Promise的解决方案来处理异步操作的代码逻辑,但是 ES6 的Generator却给异步操作又提供了新的思路, ...
随机推荐
- Lambda拉姆达表达式
拉姆达表达式常用于委托,也就是说拉姆达表达式是匿名函数,简单点就是函数. a => a.Equals("string"); //原形为: (a) => { return ...
- get_date.sh
#!/usr/bin#####################################################################日期函数处理#获取某个月份的天数 getM ...
- Arrays -数组工具类,数组转化字符串,数组排序等
package cn.learn.basic; import java.util.Arrays; /* java.util.Arrays是一个与数组相关的工具类,含有大量静态方法,用来实现数组常见的操 ...
- js 函数 写法
// function ckeckName(){}; // function checkUser(){}; // function checkPassWorld(){}; // var checkNa ...
- quartz CronExpression
一.Quartz Cron 表达式支持到七个域 名称 是否必须 允许值 特殊字符 秒 是 0-59 , - * / 分 是 0-59 , - * / 时 是 0-23 , - * / 日 是 1-31 ...
- 重温spark基本原理
(一)spark特点: 1.高效,采用内存存储中间计算结果,并通过并行计算DAG图的优化,减少了不同任务之间的依赖,降低了延迟等待时间. 2.易用,采用函数式编程风格,提供了超过80种不同的Trans ...
- Manacher(输出最长回文串及下标)
http://acm.hdu.edu.cn/showproblem.php?pid=3294 Girls' research Time Limit: 3000/1000 MS (Java/Others ...
- ROT13加密和解密
问题 ROT13(回转13位)是一种简易的替换式密码算法.它是一种在英文网络论坛用作隐藏八卦.妙句.谜题解答以及某些脏话的工具,目的是逃过版主或管理员的匆匆一瞥.ROT13 也是过去在古罗马开发的凯撒 ...
- CMS(1)
一周后,终于可以学习到可爱的渗透了哈哈哈.除了大哥给的CMS(其实可以算是只是在文件上传的时候了解一下),但是对于一个CMS完整的渗透思路,我还是不懂.首先感谢章老师给我的CMS源码哈哈哈,在我的日记 ...
- 2.WCF学习--地址
一.URI(统一资源标识) web服务可视为一种网络资源,并且可以通过一个URI来进行唯一标识.而服务通过终结点的形式发布出来,我们所说的一个服务在大部分场景中实际上指的是服务的某个终结点.终结点的核 ...