// 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使用的更多相关文章

  1. es6 generator函数的异步编程

    es6 generator函数,我们都知道asycn和await是generator函数的语法糖,那么genertaor怎么样才能实现asycn和await的功能呢? 1.thunk函数    将函数 ...

  2. ES6 Generator vs ES6 async/await

    ES6 Generator vs ES6 async/await next yield promise refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允 ...

  3. es6 generator函数

    es6 新增了Generator函数,一种异步编程的解决方案 回顾一下,es6 提供了新的遍历方法,for of ,适用于各种数据集合,统一了遍历操作,原生支持for of 集合的数据集合有.数组,字 ...

  4. ES6 Generator的应用场景

    一.基础知识 API文档 ES6 诞生以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 Promise 对象 Generator 函数将 JavaScript 异步编程带入了一个 ...

  5. ES6 Generator async

    Generator 函数是 ES6 提供的一种异步编程解决方案 async 函数使得异步操作变得更加方便,是 Generator 函数的语法糖. js单线程的原因是:避免DOM渲染冲突! 更新:201 ...

  6. ES6 Generator 学习笔记一

    Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同. Generator 函数有多种理解角度.从语法上,首先可以把它理解成,Generator 函数是一个状态机 ...

  7. ES6 generator 基础

    参考文档 harmony:generators Generator是ES6的新特性,通过yield关键字,可以让函数的执行流挂起,那么便为改变执行流程提供了可能. 创建Generator functi ...

  8. ES6:Generator函数(1)

    Generator函数是ES6提供的一种异步编程解决方案.它会返回一个遍历器对象 function* helloWorldGenerator(){ yield “hello”; yield “worl ...

  9. es6 --- Generator 函数

    第一部分,ES6 中的 Generator 在 ES6 出现之前,基本都是各式各样类似Promise的解决方案来处理异步操作的代码逻辑,但是 ES6 的Generator却给异步操作又提供了新的思路, ...

随机推荐

  1. DbWrench002--建模以及数据正向工程和反向工程的具体操作

    DbWrench--建模以及数据正向工程和反向工程 参考博客:https://my.oschina.net/u/3459265/blog/1611999 一.数据正向工程 在建模工作中画好的表与表之间 ...

  2. sourcetree for mac 使用

    1.sourceTree clone 仓库 打开sourceTree, 点击 新仓库(1) -> 从url克隆(2), 如下图 如下图所示, 粘贴源url路径, 自动补全或者手动选择目标路径和名 ...

  3. netcore之mysql中文乱码问题解决记录

    尝试了netcore代码里面设置基本无效了 https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core- ...

  4. 解决bug:sprongboot2整合shiro,swagger2页面样式加载不出来问题

    问题如题: 解决思路,把shiro拦截去掉之后发现swagger-ui.html页面接在的资源如下: 因此可以推断拦截器拦截了 "/swagger-resources" " ...

  5. No-sql之redis常用命令

    转自:http://blog.csdn.net/nicewuranran/article/details/51793760 No-SQL之Redis 介绍 Redis是一种基于内存存储的key-val ...

  6. ApplicationContextAware 快速获取bean

    在Web应用中,Spring容器通常采用声明式方式配置产生:开发者只要在web.xml中配置一个Listener,该Listener将会负责初始化Spring容器,MVC框架可以直接调用Spring容 ...

  7. UVAlive 6756 Increasing Shortest Path

    We all love short and direct problems, it is easier to write, read and understand the problem statem ...

  8. 最小生成树,Prim算法实现

    最小生成树 所谓最小生成树,就是一个图的极小连通子图,它包含原图的所有顶点,并且所有边的权值之和尽可能的小. 首先看看第一个例子,有下面这样一个带权图: 它的最小生成树是什么样子呢?下图绿色加粗的边可 ...

  9. 攻防世界--Shuffle

    测试文件:https://adworld.xctf.org.cn/media/task/attachments/a03353e605bc436798a7cabfb11be073 1.准备 获得信息 3 ...

  10. mpvue 无法获取$store的问题

    在开发的时候,我们喜欢将一些公共的方法,属性,放在一个特定的位置,例如在mpvue开发小程序的时候, 我们将其放在 vue提供的store里面,或者在mainjs中通过Vue.prototype.xx ...