学异步的解决方案,然后看到了Generator,很好的东西,记录下!
一些好的文章
http://es6.ruanyifeng.com/#docs/generator
http://es6.ruanyifeng.com/#docs/async
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/yield
Generator概念
Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
形式上,Generator函数是一个普通函数,但是有两个特征。一是,function命令与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态(yield语句在英语里的意思就是“产出”)。
yield语句
由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield语句就是暂停标志。
遍历器对象的next方法的运行逻辑如下
function* example(){ var a = 1, b = 2, c = 3; console.log(a); yield a; console.log(b) yield b; console.log(c); yield c; console.log(a+b+c); return a+b+c; } var result = example(); //这里执行完后函数里面的代码并不会执行 result.next(); //开始执行函数里面的代码 打印a的值 遇到第一个yield 返回里面的值 {value: 1, done: false} result.next(); //打印b的值 遇到第二个yield 返回里面的值 {value: 2, done: false} result.next(); //打印c的值 遇到第三个yield 返回里面的值 {value: 3, done: false} result.next(); //打印a+b+c的值 返回 {value: 3, done: false}
关于yield 要仔细记录一些东西
yield
yield 关键字用来暂停和继续一个生成器函数
语法
yield [[expression]];
用作返回值. 如果忽略, 将返回 undefined .
这个可以是表达式 yield a+b;也可以是函数 yield function(fun){fun(a+b)}
ps: 在看co源码的时候,用到的就是函数的方式,但是相关的介绍就比较少了
描述
yield 关键字使生成器函数暂停执行,并返回跟在它后面的表达式的当前值. 可以把它想成是 return 关键字的一个基于生成器的版本.
yield 关键字实际返回一个对象,包含两个属性, value 和 done. value 属性为 yield expression 的值, done 是一个布尔值用来指示生成器函数是否已经全部完成.
一旦在yield expression 处暂停, 除非外部调用生成器的 next() 方法,否则生成器的代码将不能继续执行. 这使得可以对生成器的执行以及渐进式的返回值进行直接控制.
yiled语句是表达式的例子很多了,介绍也很多,当为函数的时候就很少,主要记录下
1.当表达式为函数的时候,调用next返回的是没有value的
2.yield的函数的第一个参数(是个函数), 通过next的返回值调用value方法来设置,
一个例子来说明
function* fun(){ yield function(callback){ console.log(callback.toString()); } } var result = fun(); var step = result.next(); //返回的值{done: false} 没有value值 但是有个value这个方法 console.log(step.value) //可以看到确实有这个方法 step.value(function(){var str = "测试!!"}) //调用这个方法 参数传一个函数进去 返现这个函数当做参数传到了yield表达式的函数里面去了 //所以 后面就打印了这个函数
next方法的参数
yield句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值.
一个例子来说明上面这段话的意思
function* arg(){ var a = yield 1; console.log(a); var c = yield 3; console.log(c); } var r = arg(); r.next(); r.next(); //打印的undefined 因为a的值不是 yield里面表达式的值 r.next("your sister"); //打印your sister 因为next参数的值才是yield返回的值
如何优雅的实现异步编程了
在解决异步编程的解决方案里面,promise回调模式写成了链式结构,并且解决了串行和并行请求的方案,总之很好,浏览器支持有些也支持,不支持jquery也有类似的用法,总之很好就是了, 貌似唯一的一个缺点就是还是回调方式的.
Generator了,可以写成非回调方式的,但是在浏览器中支持不好,nodejs中却很好用,伟大的co
一个简单例子看怎么进行异步处理的
function get(url){ return function(callback) { $.ajax({ url : url, type : "get", dataType : "html", success : function(response){ callback(response); } }); } } function *ansyc(){ var html1 = yield get("http://www.cnblogs.com/aggsite/SideRight"); html1 = html1.slice(0,20) +"截取部分11111-------------------------------------------"; console.log(html1) var html2 = yield get("http://www.cnblogs.com/aggsite/UserStats"); html2 = html2.slice(0,20) +"截取部分2222-------------------------------------------"; console.log(html2); var html3 = yield get("http://www.cnblogs.com/aggsite/AggStats"); html3 = html3.slice(0,20) +"截取部分3333-------------------------------------------"; console.log(html3); } var result = ansyc(); var step = result.next() step.value(function(res){ var step1 = result.next(res); step1.value(function(res1){ var step2 = result.next(res1); step2.value(function(res2){ var step3 = result.next(res2); }); }) });
只看ansyc里面函数的部分,可以说阅读代码起来是非常的顺畅的,如果把下面的一大段异步回调封装一下调用,就可以实现优雅的异步编程了
function co(generator) { var gen = generator(); function next(result) { var step = gen.next(result); if (!step.done) { step.value(next); } } next(); } function get(url){ return function(callback) { $.ajax({ url : url, type : "get", dataType : "html", success : function(response){ callback(response); } }); } } co(function* (){ var html1 = yield get("http://www.cnblogs.com/aggsite/SideRight"); html1 = html1.slice(0,20) +"截取部分11111-------------------------------------------"; console.log(html1) var html2 = yield get("http://www.cnblogs.com/aggsite/UserStats"); html2 = html2.slice(0,20) +"截取部分2222-------------------------------------------"; console.log(html2); var html3 = yield get("http://www.cnblogs.com/aggsite/AggStats"); html3 = html3.slice(0,20) +"截取部分3333-------------------------------------------"; console.log(html3); })
这样看起来确实很舒服了,代码还很少了,不过没有提供错误的处理方式
一切看起来那么美好,但是在浏览器上面支持的非常糟糕,nodejs端到时很不错的方案.浏览器端可以用wind.js才实现
PS:Generator的内容很多,我主要只是看了实现异步编程的部分......