function * exampleGen () {
var a = yield undefined;
var b = yield a + 1;
return b;
}
var exampleIter = exampleGen();
exampleIter.next().value; // undefined
exampleIter.next(12).value; // 13 (I passed 12 back in, which is assigned to a)
exampleIter.next("Hi").value; // "Hi" is assigned to b, and then returned
這可能會讓人困惑,但是當你屈服時它就像是一個return語句;左側還沒有被賦值......而且更重要的是,如果你把var y = (yield x) + 1;
的括號解決了之前其餘的表達......所以你返回,並且+1被保留,直到值返回。
然後當它到達時(通過.next()
傳入),評估其餘表達式(然後分配到左側)。
這與每個調用返回的對象有兩個屬性{ value: ..., done: false }
value
是你返回/屈服,done
是,是否它擊中了實際return語句在函數結束時(包括隱性收益)是什麼。
這是可以用來使這種異步魔術發生的部分。
function * asyncGen (id) {
var key = yield getKeyPromise(id);
var values = yield getValuesPromise(key);
return values;
}
var asyncProcess = asyncGen(123);
var getKey = asyncProcess.next().value;
getKey.then(function (key) {
return asyncProcess.next(key).value;
}).then(function (values) {
doStuff(values);
});
沒有魔法。
而不是返回一個值,我返回一個承諾。
當承諾完成時,我正在推回結果,使用.next(result)
,這給我另一個承諾。
當這個承諾解決時,我推回來,使用.next(newResult)
,等等,直到我完成。
我們可以做得更好嗎?
我們現在知道,我們只是在等待解決的承諾,然後在結果的迭代器上調用.next
。
我們是否需要提前知道迭代器的樣子,知道什麼時候完成?
不是。
function coroutine (iterator) {
return new Promise(function (resolve, reject) {
function turnIterator (value) {
var result = iterator.next(value);
if (result.done) {
resolve(result.value);
} else {
result.value.then(turnIterator);
}
}
turnIterator();
};
}
coroutine(myGen).then(function (result) { });
這不完整和完美。 co涵蓋了額外的基礎(確保所有的收益都像承諾一樣被對待,所以你不會通過傳遞一個非承諾的價值來炸燬......或者允許承諾的數組被放棄,這成爲一個承諾將返回該結果的數組......或嘗試/捕捉承諾處理,將錯誤返回到迭代器中......是的,嘗試/ catch完美地與yield語句完美結合,這樣做,這要歸功於在迭代器上的.throw(err)
方法)。
這些東西並不難實現,但它們使得這個例子比需要的更混亂。
這正是爲什麼co或其他「協同程序」或「產卵」方法是完美的這個東西。
快速服務器背後的傢伙構建了KoaJS,使用Co作爲庫,而Koa的中間件系統只需要在其.use
方法中使用生成器並做正確的事情。
但等等,還有更多!
從ES7開始,規範很可能會爲此確切用例添加語言。
async function doAsyncProcess (id) {
var key = await getKeyPromise(id);
var values = await getValuesPromise(key);
return values;
}
doAsyncProcess(123).then(values => doStuff(values));
的async
和await
關鍵字一起使用時,以實現相同的功能的協程包裹承諾高產發生器,沒有所有的外部樣板的(並與發動機級優化,最終)。
如果您使用像BabelJS這樣的轉譯器,您可以今天試試。
我希望這會有所幫助。
你可能想看看[異步](https://github.com/caolan/async)作出異步調用井井有條,方便... – DrCord
那將不會幫助我瞭解這是如何工作的...... –