es6,promise,generator,next,yield與koa

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函數繼續往下走。

相關文章
相關標籤/搜索