es6里有了不少新特性javascript
promise是一种形式,使用promise可让异步的代码像同步代码,从而更符合人类的思惟方式,使回调函数的写法变得轻松html
在函数中使用promise,通常是return一个用promise包裹的函数,如:java
1 function t(arg){ 2 //准备工做,处理等 3 // 。。。 4 var istrue =arg+1 5 //处理结束 6 return new promise(function(resolve,reject{ 7 //断定并返回 8 if(istrue!='3'){ 9 console.log(istrue) 10 resolve(); 11 }else{ 12 reject(); 13 } 14 })) 15 } 16 t(3) 17 .then(t(1)) 18 .then(t(8)) 19 .then(t(2))
关于promise函数的感性认识能够猛击:http://www.zhangxinxu.com/wordpress/2014/02/es6-javascript-promise-%E6%84%9F%E6%80%A7%E8%AE%A4%E7%9F%A5/es6
generator就是一个状态机函数,在generator函数内部用yield关键字进行分块,在调用generator函数时,用.next()方法进入下一个状态:web
1 function* quips(name) { 2 yield "hello " + name + "!"; 3 yield "i hope you are enjoying the blog posts"; 4 if (name.startsWith("X")) { 5 yield "it's cool how your name starts with X, " + name; 6 } 7 yield "see you later!"; 8 } 9 > var iter = quips("jorendorff"); 10 [object Generator] 11 > iter.next() 12 { value: "hello jorendorff!", done: false } 13 > iter.next() 14 { value: "i hope you are enjoying the blog posts", done: false } 15 > iter.next() 16 { value: "see you later!", done: false } 17 > iter.next() 18 { value: undefined, done: true }
每次调用.next()函数的返回值是一个包含value和done两个元素的对象。promise
引用http://web.jobbole.com/82903/的话:多线程
每当 Generator 函数执行遇到 yield 表达式时,函数的栈帧 — 本地变量,函数参数,临时值和当前执行的位置,就从堆栈移除,可是 Generator 对象保留了对该栈帧的引用,因此下次调用 .next() 方法时,就能够恢复并继续执行。
然而generator并非多线程,app
在支持多线程的语言中,同一时间能够执行多段代码,并伴随着执行资源的竞争,执行结果的不肯定性和较好的性能。而 Generator 函数并非这样,当一个 Generator 函数执行时,它与其调用者都在同一线程中执行,每次执行顺序都是肯定的,有序的,而且执行顺序不会发生改变。与线程不一样,Generator 函数能够在内部的 yield 的标志点暂停执行。
使用generator来作回调:框架
function delay(time, callback){ setTimeout(function(){ callback("Slept for "+time); },time); } function run(generatorFunction) { var generatorItr = generatorFunction(resume); function resume(callbackValue) { generatorItr.next(callbackValue); } generatorItr.next() } run(function* myDelayedMessages(resume) { console.log(yield delay(1000, resume)); console.log(yield delay(1200, resume)); });
解释一下:generator函数返回一个迭代器,这里就是generatorItr,它在resume里被调用使用next(callbackValue)方法,将resume的参数callbackValue传入给yield的前的对象。koa
这里实际上就是把yield后语句的返回值传给yield前的对象,而且持续转进到下一个状态。
koa就实现了这个run方法的机制,不用咱们写了
1 'use strict' 2 var koa = require('koa') 3 var app = koa(); 4 var fs =require('fs') 5 6 app.use(function *(next){ 7 var content = yield readFileAsync('./index.html'); 8 console.log('this is '+content); 9 console.log('body. '+content); 10 this.body=content; 11 }); 12 13 function readFileAsync(fpath){ 14 return new Promise(function(resolve,reject){ 15 fs.readFile(fpath,'utf-8',function(err,content){ 16 if(err) reject(err) 17 else { 18 resolve(content)} 19 }) 20 }) 21 } 22 var port = 3001; 23 app.listen(port) 24 console.log('listening on port '+ port)
网上有一些本身实现了简单的koa框架的,咱们能够参考这些代码,来总结koa框架的使用规律。好比一个实现了koa 中的co函数及使用例子以下
1 function co(generator){ 2 var gen = generator(); 3 4 var next = function(data){ 5 var result = gen.next(data); 6 7 if(result.done) return; 8 9 if (result.value instanceof Promise) { 10 console.log("in if (result.value instanceof Promise)"); 11 result.value.then(function (d) { 12 next(d); 13 }, function (err) { 14 next(err); 15 }) 16 }else { 17 next(); 18 } 19 }; 20 21 next(); 22 } 23 co(function*(){ 24 var text1 = yield new Promise(function(resolve){ 25 console.log("in 1st Promise"); 26 setTimeout(function(){ 27 resolve("I am text1"); 28 }, 1000); 29 }); 30 31 console.log(text1); 32 33 var text2 = yield new Promise(function(resolve){ 34 setTimeout(function(){ 35 resolve("I am text2"); 36 }, 1000); 37 }); 38 39 console.log(text2); 40 });
koa use 方法中的参数必须是一个generator函数或者能够返回一个generator函数对象,这个函数假设为g,g里用yield关键字进行异步调用,而yield后必须返回一个promise对象,由于在co函数里,须要调用yield 返回的对象的then方法进行参数传递或者错误信息传递。
co函数负责取到yield返回promise对象的运行结果,并传递给yield关键字以前的值,随后调用generator函数的next方法推进generator函数继续往下走。