一般ajax請求都會用到異步調用問題,爲了保證調用順序的正確性,通常會用到callback,後來出現了promise的解決方案。
在異步編程中,還有一種解決方案,那就是generator生成器函數,這個函數會返回一個迭代器。ajax
特色:函數聲明只是多了個*號來表示這是一個生成器函數,而且通常能夠在函數內看到yield關鍵字。
原理:它會將一個函數分爲若干個小函數,而且返回一個迭代器,經過調用迭代的next方法(移動指針),內部遍歷值、狀態,保持正確的執行順序。每次調用next方法,都會向下執行一步。
用法:
1.先產出,下一個next負責傳值,而後接收新值。
2.yield後面跟着的是value值(產出值)。 yield等號前面的 是咱們當前調用next傳進來的 值。沒有等號表明不接收新值。 注意點:迭代器的第一個next執行,傳值是無效的。
function *read(){ console.log(1); var content1 = yield 'qs'; console.log(content1); var content2 = yield '9';![圖片描述][1] console.log(content2); return content2; } var it = read(); var a = it.next() //輸出 1 a:{value:'qs',done:false} var b = it.next('hello')//輸出hello b:{value:'9',done:false} var c = it.next('generator')//輸出generator c:{value:'generator',done:true} var d = it.next('123')//輸出generator c:{value:undefined,done:true} console.log(a,b,c,d)
具體的執行步驟,見圖分解npm
產出的值 是一個object,包含兩個key :value 和 done value
表示產出的值,done表示執行狀態(迭代器是否執行完成,所有遍歷一遍) 當done
爲true時表示遍歷完成。以後再次執行next,就沒有產出了,因此value爲undefined,done仍舊是true;
用處:generator通常和promise結合一塊兒用編程
let fs = require('fs'); let blueBird = require('bluebird'); let read2 = blueBird.promisify(fs.readFile); function *r(){ let content1 = yield read2('./1.txt','utf8'); let content2 = yield read2(content1,'utf8'); return content2 } let it2 = r(); it2.next().value.then(res=>{ it2.next(res).value.then(res=>{ console.log(res); console.log(it2.next(res));//須要給content2賦值,而後產出{ value: '大大大', done: true } }) });
爲了更好的結合promise使用,出現了co庫。
co庫的做用就是:把一個生成器函數的迭代器,最後一步執行完畢後,而後統一執行一個成功回調
安裝:npm install co --savepromise
let co = require('co'); function *r2(){ let content1 = yield read2('./1.txt','utf8'); let content2 = yield read2(content1,'utf8'); return content2 } co(r2).then(function(res){console.log(res,11111111111111)});
co庫實現原理,就是利用產出值的done的狀態,去判斷是否須要再次遞歸執行next方法。異步
function co(it){ return new Promise(function(resolve,reject){ function next(data){ let {value,done}= it.next(data); if(!done){ value.then(res=>{ next(res); },reject) }else{ resolve(value) } } next(); }) }