鍘熸枃锛歨ttps:/猸愶笍/juejin.cn/post/7069317318332907550
寮曡█
鏃犺鏄潰璇曡繃绋嬭繕鏄棩甯镐笟鍔″紑鍙戯紝鐩镐俊澶у鏁板墠绔紑鍙戣€呭彲浠ョ啛缁冧娇鐢?Async/Await 浣滀负寮傛浠诲姟鐨勭粓鏋佸鐞嗘柟妗堛€?/p>
浣嗘槸瀵逛簬 Async 鍑芥暟鐨勫叿浣撳疄鐜拌繃绋嬪彧鏄煡鍏剁劧涓嶇煡鎵€浠ョ劧锛屼粎浠呬簡瑙e畠鏄熀浜?Promise 鍜?Generator 鐢熸垚鍣ㄥ嚱鏁扮殑璇硶绯栥€?/p>
鎻愬強 JavaScript 涓?Async 鍑芥暟鐨勫唴閮ㄥ疄鐜板師鐞嗭紝澶у鏁板紑鍙戣€呭苟涓嶆竻妤氳繖涓€杩囩▼銆傜敋鑷充粠鏉ユ病鏈夋€濊€冭繃 Async 鎵€璋撹娉曠硸鏄浣曡 JavaScript 缁勫悎鑰屾潵鐨勩€?/p>
鍒媴蹇冿紝鏂囦腑浼氬甫浣犲垎鏋?Async 璇硶鍦ㄤ綆鐗堟湰娴忚鍣ㄤ笅鐨?polyfill 瀹炵幇锛屽悓鏃舵垜涔熶細鎵嬫妸鎵嬪甫浣犲熀浜?Promise 鍜?Generator 鏉ュ疄鐜版墍璋撶殑 Async 璇硶銆?/p>
鎴戜滑浼氫粠浠ヤ笅鏂归潰鏉ラ€愭鏀诲厠 Async 鍑芥暟鑳屽悗鐨勫疄鐜板師鐞嗭細
馃専 Promise 绔犺妭姊崇悊锛屼粠鍏ラ棬鍒版簮鐮佸甫浣犳帉鎻?Promise 搴旂敤銆?/p>
馃専 浠€涔堟槸鐢熸垚鍣ㄥ嚱鏁帮紵Generator 鐢熸垚鍣ㄥ嚱鏁板熀鏈壒寰佹⒊鐞嗐€?/p>
馃専 Generator 鏄浣曡瀹炵幇鐨勶紝Babel 濡備綍鍦ㄤ綆鐗堟湰娴忚鍣ㄤ笅瀹炵幇 Generator 鐢熸垚鍣ㄥ嚱鏁般€?/p>
馃専 浣滀负閫氱敤寮傛瑙e喅鏂规鐨?Generator 鐢熸垚鍣ㄥ嚱鏁版槸濡備綍瑙e喅寮傛鏂规銆?/p>
馃専 寮€婧?Co 搴撶殑鍩烘湰鍘熺悊瀹炵幇銆?/p>
馃専 Async/Await 鍑芥暟涓轰粈涔堜細琚О涓鸿娉曠硸锛屽畠绌剁珶鏄浣曡瀹炵幇鐨勩€?/p>
鐩镐俊璇诲畬鏂囩珷鐨勪綘锛屽浜?Async/Await 鐪熸鍙互鍋氬埌鈥滅煡鍏剁劧锛岀煡鍏舵墍浠ョ劧鈥濄€?/p>
Promise
鎵€璋?Async/Await 璇硶鎴戜滑鎻愬埌鏈川涓婂畠鏄熀浜嶱romise 鍜?Generator 鐢熸垚鍣ㄥ嚱鏁扮殑璇硶绯栥€?/p>
鍏充簬 Promise 杩欑瘒鏂囩珷涓垜灏变笉杩囦簬灞曞紑浠栫殑鍩虹鍜屽師鐞嗛儴鍒嗕簡锛岀綉缁滀腑瀵逛簬浠嬬粛 Promise 鐩稿叧鐨勬枃绔犵洰鍓嶅凡缁忛潪甯镐紭绉€浜嗐€傚鏋滄湁鍏磋叮娣卞叆 Promise 鐨勫悓瀛﹀彲浠ユ煡鐪嬶細
馃専 JavaScript Promise MDN Docs锛歨ttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promise 鍩虹浣跨敤鍑嗗垯锛孧DN 涓婄粰鍑轰簡璇﹀敖鐨勮鏄庡拰瀹炰緥锛屽己鐑堝缓璁浜?Promise 闄岀敓鐨勫悓瀛﹀彲浠ユ煡闃?MDN 宸╁浐 Promise 鍩虹鐭ヨ瘑銆?/p>馃専 Promise A+ 瑙勮寖锛歨ttps://promisesaplus.com/
Promise A+ 瀹炵幇鍑嗗垯锛屼笉鍚屾祻瑙堝櫒/鐜涓嬪浜?Promise 閮芥湁鑷繁鐨勫疄鐜帮紝瀹冧滑閮戒細渚濈収鍚屼竴瑙勮寖鏍囧噯鍘诲疄鐜?Promise 銆?/p>
鎴戝湪 鉃★笍 杩欎釜鍦板潃锛歨ttps://github.com/19Qingfeng/notes/blob/master/promise/core/index.js 鎸夌収瑙勮寖瀹炵幇杩囦竴鐗堝畬鏁寸殑 Promise 锛屾湁鍏磋叮鐨勯€氳鍙互鑷鏌ラ槄浠g爜杩涜 Promise 鍘熺悊宸╁浐銆?/p>
- 馃専 V8 Promise婧愮爜鍏ㄩ潰瑙h锛歨ttps://juejin.cn/post/7055202073511460895
鍏充簬 Promise 涓悇绉嶈竟鐣屽簲鐢ㄤ互鍙婃繁灞傛 Promise 鍘熺悊瀹炵幇锛屽缓璁湁鍏磋叮鏇存繁灞傛鐨勫悓瀛︾粨鍚堣繖绡囨枃绔犲幓鍙傜収闃呰銆?/li>
鐢熸垚鍣ㄥ嚱鏁?/h3>
鍏充簬 Generator 鐢熸垚鍣ㄥ嚱鏁颁笌 Iterator 杩唬鍣紝澶у鏁板紑鍙戣€呭湪鏃ュ父搴旂敤涓彲鑳藉苟涓嶅 Promise 閭d箞甯歌銆?/p>
鎵€浠ラ拡瀵逛簬 Generator 鎴戜細绋嶅井鍜屽ぇ瀹朵粠鍩虹寮€濮嬭璧枫€?/p>
Generator 姒傚康
Generator 鍩虹鍏ラ棬
鎵€璋?Generator 鍑芥暟瀹冩槸鍗忕▼鍦?ES6 鐨勫疄鐜帮紝鏈€澶х壒鐐瑰氨鏄彲浠ヤ氦鍑哄嚱鏁扮殑鎵ц鏉冿紙鍗虫嫢鏈夋殏鍋滃嚱鏁版墽琛岀殑鏁堟灉锛夈€?/p>
function* gen() {
yield 1;
yield 2;
yield 3;
}
let g = gen();
g.next(); // { value: 1, done: false }
g.next(); // { value: 2, done: false }
g.next(); // { value: 3, done: false }
g.next(); // { value: undefined, done: true }
g.next(); // { value: undefined, done: true }
涓婅堪鐨勫嚱鏁板氨鏄竴涓?Generator 鐢熸垚鍣ㄥ嚱鏁扮殑渚嬪瓙锛屾垜浠€氳繃鍦ㄥ嚱鏁板0鏄庡悗娣诲姞涓€涓?* 鐨勮娉曞垱寤轰竴涓悕涓?gen 鐨勭敓鎴愬櫒鍑芥暟銆?/p>
璋冪敤鍒涘缓鐨勭敓鎴愬櫒鍑芥暟浼氳繑鍥炰竴涓?Generator { }
鐢熸垚鍣ㄥ疄渚嬪璞°€?/p>
鍒濇鎺ヨЕ鐢熸垚鍣ㄥ嚱鏁扮殑鍚屽锛岀湅鍒颁笂闈㈢殑渚嬪瓙鍙兘绋嶅井浼氭湁鐐规嚨銆備粈涔堟槸 Generator 瀹炰緥瀵硅薄锛屽嚱鏁颁腑鐨?yield 鍏抽敭瀛楀張鏄仛浠€涔堢殑锛屾垜浠簲璇ュ浣曚娇鐢ㄥ畠鍛紵
鍒潃鎬ワ紝鎺ヤ笅鏉ユ垜浠潵涓€姝ヤ竴鎻紑杩欎簺杩锋儜銆?/p>
鎵€璋撹繑鍥炵殑 g 鐢熸垚鍣ㄥ璞′綘鍙互绠€鍗曠殑灏嗗畠鐞嗚В鎴愪负绫讳技杩欐牱鐨勪竴涓璞$粨鏋?
{
next: function () {
return {
done:Boolean, // done琛ㄧず鐢熸垚鍣ㄥ嚱鏁版槸鍚︽墽琛屽畬姣?瀹冩槸涓€涓竷灏斿€?
value: VALUE, // value琛ㄧず鐢熸垚鍣ㄥ嚱鏁版湰娆¤皟鐢ㄨ繑鍥炵殑鍊?
}
}
}
棣栧厛锛屾垜浠€氳繃
let g = gen()
璋冪敤鐢熸垚鍣ㄥ嚱鏁板垱寤轰簡涓€涓敓鎴愬櫒瀵硅薄 g 锛屾鏃?g 鎷ユ湁 next 涓婅堪缁撴瀯鐨?next 鏂规硶銆?br> 杩欎竴姝ワ紝鎴戜滑鎴愪负 g 涓鸿繑鍥炵殑鐢熸垚鍣ㄥ璞★紝 gen 涓虹敓鎴愬櫒鍑芥暟銆傞€氳繃璋冪敤鐢熸垚鍣ㄥ嚱鏁?gen 杩斿洖浜嗙敓鎴愬櫒瀵硅薄 g 銆?/p>涔嬪悗锛岀敓鎴愬櫒瀵硅薄涓殑 next 鏂规硶姣忔璋冪敤浼氳繑鍥炰竴娆?code>{ value:VALUE, done:boolean }鐨勫璞°€?br> 姣忔璋冪敤鐢熸垚鍣ㄥ璞$殑 next 鏂规硶浼氳繑鍥炰竴涓笂杩扮被鍨嬬殑 object:
鍏朵腑 done 琛ㄧず鐢熸垚鍣ㄥ嚱鏁版槸鍚︽墽琛屽畬姣?鑰?value 琛ㄧず鐢熸垚鍣ㄥ嚱鏁颁腑鏈 yield 瀵瑰簲鐨勫€笺€?/h6>
閮ㄥ垎娌℃湁鎺ヨЕ杩囩殑鍚屽鍙兘涓嶅お浜嗚В杩欎竴杩囩▼锛屾垜浠潵璇︾粏鎷嗗紑涓婅堪鍑芥暟鐨勬墽琛岃繃绋嬫潵鐪嬬湅锛?/p>
棣栧厛璋冪敤 gen() 鐢熸垚鍣ㄥ嚱鏁拌繑鍥?g 鐢熸垚鍣ㄥ璞°€?/p>
鍏舵杩斿洖鐨?g 鐢熸垚鍣ㄥ璞′腑鎷ユ湁涓€涓?next 鐨勬柟娉曘€?/p>
姣忓綋鎴戜滑璋冪敤 g.next() 鏂规硶鏃讹紝鐢熸垚鍣ㄥ嚱鏁扮揣璺熺潃涓婁竴娆¤繘琛屾墽琛岋紝鐩村埌鍑芥暟纰板埌 yield 鍏抽敭鍊笺€?/h6>
yield 鍏抽敭瀛椾細鍋滄鍑芥暟鎵ц骞跺皢 yield 鍚庣殑鍊艰繑鍥炰綔涓烘湰娆¤皟鐢?next 鍑芥暟鐨?value 杩涜杩斿洖銆?/p>
鍚屾椂锛屽鏋滄湰娆¤皟鐢?g.next() 瀵艰嚧鐢熸垚鍣ㄥ嚱鏁版墽琛屽畬姣曪紝閭d箞姝ゆ椂 done 浼氬彉鎴?true 琛ㄧず璇ュ嚱鏁版墽琛屽畬姣曪紝鍙嶄箣鍒欎负 false 銆?/p>
yield 鍏抽敭瀛椾細鍋滄鍑芥暟鎵ц骞跺皢 yield 鍚庣殑鍊艰繑鍥炰綔涓烘湰娆¤皟鐢?next 鍑芥暟鐨?value 杩涜杩斿洖銆?/p>
鍚屾椂锛屽鏋滄湰娆¤皟鐢?g.next() 瀵艰嚧鐢熸垚鍣ㄥ嚱鏁版墽琛屽畬姣曪紝閭d箞姝ゆ椂 done 浼氬彉鎴?true 琛ㄧず璇ュ嚱鏁版墽琛屽畬姣曪紝鍙嶄箣鍒欎负 false 銆?/p>
姣斿褰撴垜浠皟鐢?let g = gen()
鏃讹紝浼氳繑鍥炰竴涓敓鎴愬櫒鍑芥暟锛屽畠鎷ユ湁涓€涓?next 鏂规硶銆?/p>
涔嬪悗褰撶涓€娆¤皟鐢?g.next()
鏂规硶鏃讹紝浼氭墽琛岀敓鎴愬櫒鍑芥暟 gen 銆傚嚱鏁颁細杩涜鎵ц锛岀洿鍒扮鍒?yield 鍏抽敭瀛椾細杩涜鏆傚仠锛屾鏃跺嚱鏁颁細鏆傚仠鍒?yield 1
璇彞鎵ц瀹屾瘯锛屽皢 1 璧嬬粰 value
鍚屾椂鍥犱负鐢熸垚鍣ㄥ嚱鏁?gen 骞舵病鏈夋墽琛屽畬姣曪紝鎵€浠ユ鏃?done 搴旇涓?false 銆傛墍浠ユ鏃堕娆¤皟鐢?g.next() 鍑芥暟杩斿洖鐨勫簲璇ユ槸 { value: 1, done: false }銆?/p>
涔嬪悗锛屾垜浠浜屾璋冪敤 g.next()
鏂规硶鏃讹紝鍑芥暟浼氫粠涓婁竴娆$殑涓柇缁撴灉鍚庤繘琛屾墽琛屻€備篃灏辨槸浼氱户缁?yield 2
璇彞銆?/p>
褰撻亣鍒?yield 2
鏃讹紝鍙堝洜涓虹鍒颁簡 yield 璇彞銆傛鏃跺嚱鏁板張浼氳涓柇锛屽洜涓烘鏃跺嚱鏁板苟娌℃湁鎵ц瀹屾垚锛屽苟涓攜ield 璇彞鍚庣揣鎸ㄧ潃鐨勬槸 2 鎵€浠ョ浜屼釜 g.next()
浼氳繑鍥?{ value: 2 , done: false }
銆?/p>
鍚屾牱锛寉ield 3; 鍥炲拰鍓嶄袱娆℃墽琛岄€昏緫鐩稿悓銆?/p>
闇€瑕侀澶栨敞鎰忕殑鏄紝褰撴垜浠鍥涙璋冪敤杩唬鍣?g.next()
鏃讹紝鍥犱负绗笁娆?g.next()
缁撴潫鏃剁敓鎴愬櫒鍑芥暟宸茬粡鎵ц瀹屾瘯浜嗐€傛墍浠ュ啀娆¤皟鐢?g.next()
鏃讹紝鐢变簬鍑芥暟缁撴潫 done 浼氬彉涓?false 銆傚悓鏃跺洜涓哄嚱鏁颁笉瀛樺湪杩斿洖鍊硷紝鎵€浠?value 涓?undefined銆?/p>
涓婅竟鏄竴涓熀浜?Generator 鍑芥暟鐨勭畝鍗曟墽琛岃繃绋嬶紝鍏跺疄瀹冪殑鏈川闈炲父绠€鍗曪細
璋冪敤鐢熸垚鍣ㄥ嚱鏁颁細杩斿洖涓€涓敓鎴愬櫒瀵硅薄锛屾瘡娆¤皟鐢ㄧ敓鎴愬櫒瀵硅薄鐨?next 鏂规硶浼氭墽琛屽嚱鏁板埌涓嬩竴娆?yield 鍏抽敭瀛楀仠姝㈡墽琛岋紝骞朵笖杩斿洖涓€涓?{ value: Value, done: boolean }
鐨勫璞°€?/h6>
涓婅堪鎵ц杩囩▼锛屾垜绋嶇◢鐢ㄤ簡涓€浜涚瘒骞呮潵鎻忚堪杩欎竴绠€鍗曠殑杩囩▼銆傚鏋滅湅鍒拌繖閲屼綘杩樻槸娌℃湁涓婇潰鐨?Demo 鍚箟锛岄偅涔堟鏃惰浣犲仠涓嬪線涓嬬殑杩涘害锛屼細鍒板紑澶翠竴瀹氳鎼炴竻妤氳繖涓畝鍗曠殑 Demo 銆?/p>
Generator 鍑芥暟杩斿洖鍊?/h5>
鍦ㄦ帉鎻′簡鍩虹 Generator 鍑芥暟鍜?yield 鍏抽敭瀛楀悗锛岃秮鐑墦閾佽鎴戜滑鏉ヤ竴涓炬敾鍏?Generator 鐢熸垚鍣ㄥ嚱鏁扮殑杩涢樁璇硶銆?/p>
鑰佹牱瀛愶紝鎴戜滑鍏堟潵鐪嬭繖鏍蜂竴娈典唬鐮侊細
function* gen() {
const a = yield 1;
console.log(a,'this is a')
const b = yield 2;
console.log(b,'this is b')
const c = yield 3;
console.log(c,'this is c')
}
let g = gen();
g.next(); // { value: 1, done: false }
g.next('param-a'); // { value: 2, done: false }
g.next('param-b'); // { value: 3, done: false }
g.next('param-c'); // { value: undefined, done: true }
// 鎺у埗鍙颁細鎵撳嵃:
// param-a this is a
// param-b this is b
// param-c this is c
杩欓噷锛屾垜浠潃閲嶆潵鐪嬬湅璋冪敤鐢熸垚鍣ㄥ璞$殑 next 鏂规硶浼犲叆鍙傛暟鏃剁┒绔熶細鍙戠敓浠€涔堜簨鎯咃紝鐞嗚В next()
鏂规硶鐨勫弬鏁版槸鍚庣画 Generator 瑙e喅寮傛鐨勯噸鐐瑰疄鐜版€濊矾銆?/p>
涓婃枃鎴戜滑鎻愬埌杩囷紝鐢熸垚鍣ㄥ嚱鏁颁腑鐨?yield 鍏抽敭瀛椾細鏆傚仠鍑芥暟鐨勮繍琛岋紝绠€鍗曟潵璇存瘮濡傛垜浠涓€娆¤皟鐢?g.next()
鏂规硶鏃跺嚱鏁颁細鎵ц鍒?yield 1
璇彞锛屾鏃跺嚱鏁颁細琚殏鍋溿€?/p>
褰撶浜屾璋冪敤 g.next()
鏂规硶鏃讹紝鐢熸垚鍣ㄥ嚱鏁颁細缁х画浠庝笂涓€娆℃殏鍋滅殑璇彞寮€濮嬫墽琛屻€傝繖閲屾湁涓€涓渶瑕佹敞鎰忕殑鐐癸細
褰撶敓鎴愬櫒鍑芥暟鎭㈠鎵ц鏃讹紝鍥犱负涓婁竴娆℃墽琛屽埌 const a = yield 1
璇彞鐨勫彸鍗婃骞舵病鏈夌粰 const a
杩涜璧嬪€笺€?/h6>
閭d箞姝ゆ椂鐨勮祴鍊艰鍙?const a = yield 1
锛?code>a浼氳璧嬩负浠€涔堝€煎憿锛熺粏蹇冪殑鍚屽鍙兘宸茬粡鍙戠幇浜嗐€傛垜浠湪 g.next('param-a')
浼犲叆鐨勫弬鏁?code>param-a 浼氫綔涓虹敓鎴愬櫒鍑芥暟閲嶆柊鎵ц鏃讹紝涓婁竴娆?yield
璇彞鐨勮繑鍥炲€艰繘琛屾墽琛屻€?/p>
绠€鍗曟潵璇达紝涔熷氨鏄皟鐢?g.next('param-a')
鎭㈠鍑芥暟鎵ц鏃讹紝鐩稿綋浜庡皢鐢熸垚鍣ㄥ嚱鏁颁腑鐨?const a = yield 1
; 鍙樻垚const a = 'param-a';
杩涜鎵ц銆?/p>
杩欐牱锛岀浜屾璋冪敤 g.next('param-a')
鏃惰嚜鐒跺氨鎵撳嵃鍑轰簡 param-a this is a
銆?/p>
鍚屾牱褰撴垜浠涓夋璋冪敤 g.next('param-b')
鏃讹紝鏈璋冪敤 next 鍑芥暟浼犲叆鐨勫弬鏁颁細琚綋浣?yield 2
杩愮畻缁撴灉璧嬪€肩粰b
鍙橀噺锛屾墽琛屽埌鎵撳嵃鏃朵細杈撳嚭 param-b this is b
銆?/p>
鍚岀悊 g.next('paramc')
浼氳緭鍑?param-c this is b
銆?/p>
鎬昏€岃█涔嬶紝褰撴垜浠负 next
浼犻€掑€艰繘琛岃皟鐢ㄦ椂锛屼紶鍏ョ殑鍊间細琚綋浣滀笂涓€娆$敓鎴愬櫒鍑芥暟鏆傚仠鏃?yield 鍏抽敭瀛楃殑杩斿洖鍊煎鐞嗐€?/h6>
鑷劧锛岀涓€娆¤皟鐢?code>g.next()浼犲叆鍙傛暟鏄鏃犳剰涔夌殑銆傚洜涓洪娆¤皟鐢?next 鍑芥暟鏃讹紝鐢熸垚鍣ㄥ嚱鏁板苟娌℃湁浠讳綍鎵ц鑷劧涔熸病鏈?yield
鍏抽敭瀛楀鐞嗐€?/p>
鎺ヤ笅鏉ユ垜浠潵鐪嬬湅鎵€璋撶殑鐢熸垚鍣ㄥ嚱鏁拌繑鍥炲€?
function* gen() {
const a = yield 1;
console.log(a, 'this is a');
const b = yield 2;
console.log(b, 'this is b');
const c = yield 3;
console.log(c, 'this is c');
return 'resultValue'
}
let g = gen();
g.next(); // { value: 1, done: false }
g.next('param-a'); // { value: 2, done: false }
g.next('param-b') // { value: 3, done: false }
g.next() // { value: 'resultValue', done: true }
g.next() // { value: undefined, done: true }
褰撶敓鎴愬櫒鍑芥暟瀛樺湪 return
杩斿洖鍊兼椂锛屾垜浠細鍦ㄧ鍥涙璋冪敤 g.next()
鍑芥暟鎭㈠鎵ц锛屾鏃剁敓鎴愬櫒鍑芥暟缁х画鎵ц鍑芥暟鎵ц瀹屾瘯銆?/p>
姝ゆ椂鑷劧 done 浼氬彉涓?true 琛ㄧず鐢熸垚鍣ㄥ嚱鏁板凡缁忔墽琛屽畬姣曪紝涔嬪悗锛岀敱浜庡嚱鏁板瓨鍦ㄨ繑鍥炲€兼墍浠ラ殢涔嬫湰娆$殑 value 浼氬彉涓?code>'resultValue'銆?/p>
涔熷氨鏄綋鐢熸垚鍣ㄥ嚱鏁版墽琛屽畬姣曟椂锛屽師鏈湰娆¤皟鐢?next 鏂规硶杩斿洖鐨?{done:true,value:undefined}
鍙樹负浜?code>{ done:true,value:'resultValue'}銆?/p>
鍏充簬 Generator 鍑芥暟鐨勫熀鏈娇鐢ㄦ垜浠氨浠嬬粛鍒拌繖閲岋紝鎺ヤ笅鏉ユ垜浠潵鐪嬬湅瀹冩槸濡備綍琚?JavaScript 瀹炵幇鐨勩€?/p>
Generator 鍘熺悊瀹炵幇
鍏充簬 Generator 鍑芥暟鐨勫師鐞嗗叾瀹炲拰鎴戜滑鍚庣画鐨勫紓姝ュ叧绯诲苟涓嶆槸寰堝ぇ锛屼絾鏄湰鐫€鈥滅煡鍏剁劧锛岀煡鍏舵墍浠ョ劧鈥濈殑鍑哄彂鐐广€?/p>
甯屾湜澶у鍙互鑰愬績鍘婚槄璇绘湰灏忕粨锛屽叾瀹炲畠鐨勫唴閮ㄨ繍琛屾満鍒跺苟涓嶆槸寰堝鏉傘€傜瑪鑰呰嚜宸变篃鍦ㄦ煇鐢靛晢澶у巶闈㈣瘯涓闂埌杩囧浣曞疄鐜?Generator 鐨?polyfill銆?/p>
棣栧厛锛屼綘鍙互鎵撳紑閾炬帴鏌ョ湅鎴戝凡缁忕紪杈戝ソ鐨?鉃★笍 Babel Generator Demo[1]銆?/p>
涔嶄竴鐪嬩篃璁稿緢澶氬悓瀛︿細绋嶅井鏈夌偣鎳碉紝娌″叧绯汇€傝繖娈典唬鐮佸苟涓嶉毦锛岄毦鐨勬槸浣犲鏈煡鎭愭儳鐨勫績鎬併€?/h6>
杩欐槸 Babel 鍦ㄤ綆鐗堟湰娴忚鍣ㄤ笅涓烘垜浠疄鐜扮殑 Generator 鐢熸垚鍣ㄥ嚱鏁扮殑 polyfill[2
] 瀹炵幇銆?/p>
宸︿晶涓?ES6 涓殑鐢熸垚鍣ㄨ娉曪紝鍙充晶涓鸿浆璇戝悗鐨勫吋瀹逛綆鐗堟湰娴忚鍣ㄧ殑瀹炵幇銆?/p>
棣栧厛宸︿晶鐨?gen 鐢熸垚鍣ㄥ嚱鏁拌鍦ㄥ彸渚ц杞寲鎴愪负浜嗕竴涓畝鍗曠殑鏅€氬嚱鏁帮紝鍏蜂綋 gen 鍑芥暟鍐呭鎴戜滑鍏堝拷鐣ュ畠銆?/p>
鍦ㄥ彸渚т唬鐮佷腑锛屽浜庢櫘閫?gen 鍑芥暟鍖呰9浜嗕竴灞俙 regeneratorRuntime.mark(gen) 澶勭悊锛屽湪婧愮爜涓繖涓€姝ュ叾瀹炰负浜嗗皢鏅€?gen 鍑芥暟缁ф壙 GeneratorFunctionPrototype 浠庤€屽疄鐜板皢 gen() 杩斿洖鐨勫璞″彉鎴?Generator 瀹炰緥瀵硅薄鐨勫鐞嗐€?/p>
杩欎竴姝ュ浜庢垜浠悊瑙?Generator 鏄惧緱骞朵笉鏄偅涔堥噸瑕侊紝鎵€浠ユ垜浠彲浠ョ畝鍗曠殑灏?regeneratorRuntime.mark 鏀瑰啓鎴愪负杩欐牱鐨勭粨鏋?
// 鑷繁瀹氫箟regeneratorRuntime瀵硅薄
const regeneratorRuntime = {
// 瀛樺湪mark鏂规硶锛屾帴鍙椾紶鍏ョ殑fn銆傚師灏佷笉鎳傜殑杩斿洖fn
mark(fn) {
return fn
}
}
鎴戜滑鑷繁瀹氫箟浜?regeneratorRuntime 瀵硅薄锛屽苟涓斾负浠栧畾涔変簡涓€涓?mark 鏂规硶銆傚畠鐨勪綔鐢ㄩ潪甯哥畝鍗曪紝鎺ュ彈涓€涓嚱鏁颁綔涓哄叆鍙傚苟涓旇繑鍥炲嚱鏁帮紝浠呮鑰屽凡銆?/p>
涔嬪悗鎴戜滑鍐嶆潵杩涘叆 gen 鍑芥暟鍐呴儴锛屽湪宸︿晶婧愪唬鐮佷腑褰撴垜浠皟鐢?gen()
鏃讹紝鏄細杩斿洖涓€涓?Iterator 瀵硅薄锛堝畠鎷ユ湁 next 鏂规硶锛屽苟涓旀瘡娆¤皟鐢?next 閮戒細杩斿洖 {value:VALUE,done:boolean}
锛夈€?/p>
鎵€浠ュ湪鍙充晶鎴戜滑浜嗚В鍒颁簡锛屾垜浠€氳繃璋冪敤缂栬瘧鍚庣殑鏅€?gen() 鍑芥暟搴旇鍜屽彸渚ц繑鍥炰竴鑷达紝鎵€璋?regeneratorRuntime.wrap() 鏂规硶涔熷簲璇ヨ繑鍥炰竴涓叿鏈?next 灞炴€х殑杩唬鍣ㄥ璞°€?/p>
鍏充簬 regeneratorRuntime.wrap() 鏂规硶锛岃繖閲屼紶鍏ヤ簡涓や釜鍙傛暟锛岀涓€涓弬鏁版槸涓€涓帴鍙椾紶鍏?context 鐨勫嚱鏁帮紝绗簩涓弬鏁版槸鎴戜滑涔嬪墠澶勭悊鐨?_marked 瀵硅薄銆?/p>
鍚屾牱鍏充簬 wrap() 鏂规硶鐨勭浜屼釜鍙傛暟鎴戜滑涓嶇敤杩囧绾犵粨锛屽畠浠嶇劧鏄浜庣紪璇戝悗鐨勭敓鎴愬櫒鍑芥暟浣滀负缁ф壙浣跨敤鐨勪竴涓弬鏁帮紝骞朵笉褰卞搷鍑芥暟鐨勬牳蹇冮€昏緫銆傛墍浠ユ垜浠殏鏃跺拷鐣ュ畠銆?/p>
姝ゆ椂锛屾垜浠簡瑙e埌锛宺egeneratorRuntime 瀵硅薄涓婂簲璇ュ瓨鍦ㄤ竴涓?wrap 鏂规硶锛屽苟涓?wrap 鏂规硶搴旇杩斿洖涓€涓弧瓒?code>杩唬鍣ㄥ崗璁甗3]鐨勫璞°€?/p>
// 鑷繁瀹氫箟regeneratorRuntime瀵硅薄
const regeneratorRuntime = {
// 瀛樺湪mark鏂规硶锛屾帴鍙椾紶鍏ョ殑fn銆傚師灏佷笉鎳傜殑杩斿洖fn
mark(fn) {
return fn
},
wrap(fn) {
// ...
return {
next() {
done: ...,
value: ...
}
}
}
璁╂垜浠繘鍏?regeneratorRuntime.wrap 鍐呴儴浼犲叆鐨勫叿浣撳嚱鏁版潵鐪嬬湅锛?/p>
function gen() {
var a, b, c;
return regeneratorRuntime.wrap(function gen$(_context) {
// while(1) 閰嶅悎鍑芥暟鐨剅eturn娌℃湁浠讳綍瀹為檯鎰忎箟
// 閫氬父鍦ㄧ紪绋嬩腑浣跨敤 while(1) 鏉ヨ〃绀簑hile涓殑鍐呴儴浼氳澶氭鎵ц
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
_context.next = 2;
return 1;
case 2:
a = _context.sent;
console.log(a, 'this is a');
_context.next = 6;
return 2;
case 6:
b = _context.sent;
console.log(b, 'this is b');
_context.next = 10;
return 3;
case 10:
c = _context.sent;
console.log(c, 'this is c');
case 12:
case 'end':
return _context.stop();
}
}
}, _marked);
}
regeneratorRuntime.wrap 鍐呴儴浼犲叆鐨勫嚱鏁帮紝浣跨敤浜?while(1) 鍐呴儴閫昏緫锛屽洜涓烘垜浠湪 while 寰幆涓厤鍚堜簡鍑芥暟鐨?return 璇彞锛屾墍浠ヨ繖閲?while(1) 鍏跺疄骞舵病鏈変换浣曞惈涔夈€?/p>
閫氬父锛屽湪缂栫▼涓垜浠敤 while(1) 鏉ヨ〃绀哄唴閮ㄧ殑閫昏緫浼氳鎵ц寰堝娆★紝鐨勭‘鍦ㄥ嚱鏁板唴閮ㄧ殑 while 寰幆姣忔璋冪敤 next 鏂规硶鍏跺疄閮戒細杩涘叆杩欐閫昏緫鎵ц銆?/p>
棣栧厛鎴戜滑鏉ョ湅鐪?浼犲叆鐨?_context 鍙傛暟瀛樺湪鍝簺灞炴€э細
_context.prev 琛ㄧず鏈鐢熸垚鍣ㄥ嚱鏁版墽琛屾椂鐨勬寚閽堜綅缃€?/p>
_context.next 琛ㄧず涓嬫鐢熸垚鍣ㄥ嚱鏁拌皟鐢ㄦ椂鐨勬寚閽堜綅缃€?/p>
_context.sent 琛ㄧず璋冪敤 g.next(params) 鏃讹紝浼犲叆鐨?params 鍙傛暟銆?/p>
_context.stop 琛ㄧず褰撹皟鐢?g.next() 鐢熸垚鍣ㄥ嚱鏁版墽琛屽畬姣曡皟鐢ㄧ殑鏂规硶銆?/p>
鍦ㄨВ閲婁簡 _context 瀵硅薄涓婄殑灞炴€у惈涔変箣鍚庯紝涔熻浣犺繕鏄笉澶槑鐧藉畠浠悇鑷殑鍚箟銆傛垜浠厛鏉ョ湅鐪嬬畝鍖栧悗鐨勫疄鐜颁唬鐮侊細
const regeneratorRuntime = {
// 瀛樺湪mark鏂规硶锛屾帴鍙椾紶鍏ョ殑fn銆傚師灏佷笉鎳傜殑杩斿洖fn
mark(fn) {
return fn;
},
wrap(fn) {
const _context = {
next: 0, // 琛ㄧず涓嬩竴娆℃墽琛岀敓鎴愬櫒鍑芥暟鐘舵€佹満switch涓殑涓嬫爣
sent: '', // 琛ㄧずnext璋冪敤鏃跺€欎紶鍏ョ殑鍊?浣滀负涓婁竴娆ield杩斿洖鍊?
done: false, // 鏄惁瀹屾垚
// 瀹屾垚鍑芥暟
stop() {
this.done = true;
},
};
return {
next(param) {
// 1. 淇敼涓婁竴娆ield杩斿洖鍊间负context.sent
_context.sent = param;
// 2.鎵ц鍑芥暟 鑾峰緱鏈杩斿洖鍊?
const value = fn(_context);
// 3. 杩斿洖
return {
done: _context.done,
value,
};
},
};
},
};
瀹屾暣鐨?regeneratorRuntime 瀵硅薄灏卞儚涓婅竟瀹炵幇鐨勯偅鏍凤紝瀹冪湅璧锋潵闈炲父绠€鍗曞鍚с€?/p>
鍦?wrap 鍑芥暟涓紝鎴戜滑鎺ュ彈浼犲叆鐨勪竴涓姸鎬佹満鍑芥暟銆傛瘡娆¤皟鐢?wrap() 鏂规硶杩斿洖鐨?next(param) 鏂规硶鏃讹紝浼氬皢 next(param) 涓紶鍏ョ殑鍙傛暟浼犻€掔粰 wrap 鍑芥暟涓殑缁存姢鐨?_context.sent 浣滀负妯℃嫙涓婁竴娆?yield 杩斿洖鍊艰€屽嚭鐜般€?/p>
鍚屾椂鍦?wrap(fn) 涓紶鍏ョ殑 fn 浣犲彲浠ュ皢瀹冪湅浣滀竴涓皬鍨嬬姸鎬佹満 锛屾瘡娆¤皟鐢?next() 鏂规硶閮戒細鎵ц鐘舵€佹満 fn 鍑芥暟銆?/p>
涓嶈繃锛屽洜涓虹姸鎬佹満涓瘡娆℃墽琛屾椂 _context.prev 鐨勫€奸兘鏄笉鍚岀殑閫犳垚浜嗘瘡娆¤皟鐢?next 鍑芥暟閮芥墽琛岀殑鏄姸鎬佹満涓笉鍚岀殑閫昏緫銆?/p>
鐩村埌锛岀姸鎬佹満鍑芥暟 fn 涓殑 switch 璇彞鍖归厤瀹屾垚杩斿洖 _context.stop() 鍑芥暟锛屾鏃跺皢 _context.done 鍙樹负 true 骞朵笖杩斿洖瀵瑰簲瀵硅薄銆?/p>
鎵€璋?Generator 鏍稿績浠g爜绠€鍖栧悗涓嶈繃涓婅堪鐭煭鍑犲崄琛岋紝瀹冪殑鍐呴儴鏍稿績鎬濇兂鏈川涓婂氨鏄€氳繃 regeneratorRuntime.wrap 鍑芥暟鍖呰9涓€涓姸鎬佹満鍑芥暟 fn 銆?/h6>
wrap 鍑芥暟鍐呴儴缁存姢涓€涓?_context 瀵硅薄锛屼粠鑰屾瘡娆¤皟鐢ㄨ繑鍥炵殑鐢熸垚鍣ㄥ璞$殑 next 鏂规硶鏃讹紝琚寘瑁圭殑鐘舵€佹満鍑芥暟鏍规嵁 _context 鐨勫搴斿睘鎬у尮閰嶅搴旂姸鎬佹潵瀹屾垚涓嶅悓鐨勯€昏緫銆?/h6>
Generator 鏍稿績鍘熺悊鍏跺疄灏辨槸杩欐牱锛屾湁鍏磋叮浜嗚В瀹屾暣浠g爜鐨勫悓瀛﹀彲浠ユ煡鐪?facebook/regenerator[4]銆?/p>
Generator 寮傛瑙e喅鏂规
Generator 鏍稿績鍘熺悊鍏跺疄灏辨槸杩欐牱锛屾湁鍏磋叮浜嗚В瀹屾暣浠g爜鐨勫悓瀛﹀彲浠ユ煡鐪?facebook/regenerator[4]銆?/p>
Generator 寮傛瑙e喅鏂规
鍦ㄨ杩板畬 Generator 鐨勫熀纭€姒傚康鍜?polyfill 鍘熺悊涔嬪悗锛屾垜浠潵姝ュ叆寮傛鐬х灖瀹冩槸濡備綍琚簲鐢ㄥ湪寮傛缂栫▼涓殑銆?/p>
澶у鏁版儏鍐典笅锛屾垜浠細鐩存帴浣跨敤 Promise 鏉ュ鐞嗗紓姝ラ棶棰樸€侾romise 甯姪鎴戜滑瑙e喅浜嗛潪甯哥碂绯曠殑鈥滃洖璋冨湴鐙扁€濆紡鐨勫紓姝ヨВ鍐虫柟妗堛€?/p>
浣嗘槸 Promise 涓粛鐒堕渶瑕佸瓨鍦ㄤ笉鍋滅殑 .then .then 褰撳紓姝ュ祵濂楄繃澶氱殑鎯呭喌涓嬶紝Promise 涓殑 then 寮忚皟鐢ㄤ篃鏄惧緱涓嶆槸閭d箞涓€绉嶇洿瑙傘€?/p>
姣忓綋闂鐨勪骇鐢熶竴瀹氫細浼撮殢瑙e喅鏂规鐨勫嚭鐜帮紝鍦?Promise 澶勭悊寮傛闂鏃讹紝Generator 鏄剧劧浣滀负瑙e喅鏂规鍑虹幇鍦ㄤ簡鎴戜滑鐨勮閲庝腑銆?/p>
function promise1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('1');
}, 1000);
});
}
function promise2(value) {
return new Promise((resolve) => {
setTimeout(() => {
resolve('value:' + value);
}, 1000);
});
}
function* readFile() {
const value = yield promise1();
const result = yield promise2(value);
return result;
}
鎴戜滑鏉ョ湅鐪嬩笂杩扮殑浠g爜锛宺eadFile 鍑芥暟鏄笉鏄◢寰湁涓€浜?async 鍑芥暟鐨勫奖瀛愩€?/p>
鍋囧鎴戞湡鏈涙墍璋?readFile() 鏂规硶鍜?async 鍑芥暟琛屼负涓€鑷达紝杩斿洖鐨?result 鍚屾牱鏄竴涓?Promise 骞朵笖淇濇寔涓婅瘔浠g爜鐨勫啓娉曪紝鎴戜滑搴旇濡備綍鍋氾紵
鐪嬪埌杩欓噷锛屼綘鍙互绋嶅井鎬濊€冧笅搴旇濡備綍鍒╃敤 Generator 鍑芥暟鐨勭壒鎬у幓瀹炵幇銆?/p>
涓婅竟鎴戜滑鎻愬埌杩囩敓鎴愬櫒鍑芥暟鍏锋湁鍙殏鍋滅殑鐗圭偣锛屽綋璋冪敤鐢熸垚鍣ㄥ嚱鏁板悗浼氳繑鍥炰竴涓敓鎴愬櫒瀵硅薄銆傛瘡娆¤皟鐢ㄧ敓鎴愬櫒瀵硅薄鐨?next 鏂规硶锛岀敓鎴愬櫒鍑芥暟鎵嶄細缁х画寰€涓嬫墽琛岀洿鍒扮鍒颁笅涓€涓?yield 璇彞锛屽悓鏃舵瘡娆¤皟鐢ㄧ敓鎴愬櫒瀵硅薄鐨?next(param) 鏂规硶鏃讹紝鎴戜滑鍙互浼犲叆涓€涓弬鏁颁綔涓轰笂涓€娆?yield 璇彞鐨勮繑鍥炲€笺€?/h6>
鍒╃敤涓婅堪鐗规€э紝鎴戜滑鍙互鍐欏嚭濡備笅鐨勪唬鐮侊細
function promise1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('1');
}, 1000);
});
}
function promise2(value) {
return new Promise((resolve) => {
setTimeout(() => {
resolve('value:' + value);
}, 1000);
});
}
function* readFile() {
const value = yield promise1();
const result = yield promise2(value);
return result;
}
function asyncGen(fn) {
const g = fn(); // 璋冪敤浼犲叆鐨勭敓鎴愬櫒鍑芥暟 杩斿洖鐢熸垚鍣ㄥ璞?
// 鏈熸湜杩斿洖涓€涓狿romise
return new Promise((resolve) => {
// 棣栨璋冪敤 g.next() 鏂规硶锛屼細鎵ц鐢熸垚鍣ㄥ嚱鏁扮洿鍒扮鍒扮涓€涓獃ield鍏抽敭瀛?
// 杩欓噷浼氭墽琛屽埌 yield promise1() 鍚屾椂灏?promise1() 杩斿洖涓鸿凯浠e櫒瀵硅薄鐨?value 鍊?
const { value, done } = g.next();
// 鍥犱负value涓篜romise 鎵€浠ュ彲浠ョ瓑寰卲romise瀹屾垚鍚庯紝鍦╰hen鍑芥暟涓户缁皟鐢?g.next(res) 鎭㈠鐢熸垚鍣ㄥ嚱鏁扮户缁墽琛?
value.then((res) => {
// 鍚屾椂绗簩娆¤皟鐢╣.next() 鏃舵槸鍦ㄤ笂涓€娆¤繑鍥炵殑promise.then涓?
// 鎴戜滑鍙互鎷垮埌涓婁竴娆romise鐨剉alue鍊间篃灏辨槸 '1'
// 浼犲叆g.next('1') 浣滀负涓婁竴娆ield鐨勫€?杩欓噷鐩稿綋浜?const value = '1'
const { value, done } = g.next(res);
// 鍚岀悊锛岀户缁笂杩拌繃绋?
value.then(resolve);
});
});
}
asyncGen(readFile).then((res) => console.log(res)); // value: 1
鎴戜滑閫氳繃瀹氫箟浜嗕竴涓?asyncGen 鍑芥暟鏉ュ寘瑁?readFile 鐢熸垚鍣ㄥ嚱鏁帮紝鍒╃敤浜嗙敓鎴愬櫒鍑芥暟缁撳悎 yield 鍏抽敭瀛楀彲浠ヨ鏆傚仠鐨勭壒鐐癸紝鍚屾椂缁撳悎 Promise.prototype.then 鏂规硶鐨勭壒鎬у疄鐜颁簡绫讳技浜?async 鍑芥暟鐨勫紓姝ュ啓娉曘€?/p>
鐪嬩笂鍘诲畠鍜?async 寰堝儚瀵瑰惂锛屼笉杩囩洰鍓嶇殑浠g爜瀛樺湪涓€涓嚧鍛界殑闂锛?/p>
asyncGen 鍑芥暟骞朵笉鍏峰閫氱敤鎬э紝涓婅竟鐨勪緥瀛愪腑 readFile 鍑芥暟鍐呴儴鍖呰9浜嗕袱灞?yield 澶勭悊鐨?promise锛屾垜浠湪 asyncGen 鍑芥暟鍐呴儴鍚屾牱涓ゆ璋冪敤 g.next() 鏂规硶銆?/p>
濡傛灉鎴戜滑鍖呰9涓夊眰 yield 澶勭悊鐨?Promise 锛岄偅涔堟垜鏄笉鏄噸鏂颁功鍐?asyncGen 鍑芥暟閫昏緫銆傚張鎴栬€?readFile 涓瓨鍦ㄦ瘮濡?yield '1'
骞朵笉鏄?Promise 鐨勮鍙ワ紝閭d箞鎴戜滑褰撲綔 Promise 浣跨敤 then 鏂规硶澶勭悊鑲畾鏄細鎶ラ敊銆?/p>
杩欐牱鐨勬柟娉曚笉鍏峰浠讳綍閫氱敤鎬э紝鎵€浠ュ湪瀹為檯椤圭洰涓病鏈変汉浼氳繖鏍峰幓缁勭粐寮傛浠g爜銆備絾鏄€氳繃杩欎釜渚嬪瓙鎴戠浉淇′綘宸茬粡鍙互鍒濇浜嗚В Generator 鐢熸垚鍣ㄥ嚱鏁版槸濡備綍缁撳悎 Promise 鏉ヤ綔涓哄紓姝ヨВ鍐虫柟妗堢殑銆?/p>
tj/co
涓婅竟鎴戜滑浣跨敤 Generator 浣滀负寮傛瑙e喅鏂规锛屾垜浠紪鍐欎簡涓€涓悕涓?asyncGen 鐨勫寘瑁瑰嚱鏁帮紝鍙槸瀹冨苟涓嶅叿澶囦换浣曢€氱敤鎬с€?/p>
鎺ヤ笅鏉ユ垜浠潵鎬濊€冨浣曡杩欎釜鏂规硶鍙樺緱鏇村姞閫氱敤锛屼粠鑰屽湪鍚勭涓嶅悓鍦烘櫙涓嬪幓鏇村ソ鐨勮В鍐冲紓姝ラ棶棰橈細
鍚屾牱锛屾垜甯屾湜鎴戠殑 readFile 鏂规硶涔﹀啓鏃舵柟寮忓拰涔嬪墠涓€鏍风洿瑙傦細
function promise1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('1');
}, 1000);
});
}
function promise2(value) {
return new Promise((resolve) => {
setTimeout(() => {
resolve('value:' + value);
}, 1000);
});
}
function* readFile() {
const value = yield promise1();
const result = yield promise2(value);
return result;
}
鍦ㄨ繖涔嬪墠鎴戜滑浣跨敤 Generator 鐨勭壒鎬ф潵澶勭悊 Promise 鐨勫紓姝ラ棶棰橈紝姣忔閮藉偦鍌荤殑鍘绘牴鎹?yeild 鍏抽敭瀛楀幓宓屽鍑芥暟閫昏緫澶勭悊銆?/p>
涓€浜涘悓瀛﹀彲鑳戒箣鍓嶅氨鎯冲埌浜嗭紝瀵逛簬鏃犵┓鏃犲敖鐨勫祵濂楄皟鐢ㄩ€昏緫鍚屾椂鍙堝瓨鍦ㄨ竟鐣屽仠姝㈡潯浠躲€傞偅涔堝綋鎴戜滑闇€瑕佸皝瑁呭嚭涓€涓叿鏈夐€氱敤鎬х殑鍑芥暟鏃讹紝浣跨敤閫掑綊鏉ュ鐞嗕笉鏄洿濂藉悧锛?/p>
鎴栬鏍规嵁杩欎釜鎬濊矾锛屼綘鍏堝彲浠ュ皾璇曡嚜宸卞皝瑁呬竴涓嬨€?/p>
涓嶅崠鍏冲瓙浜嗭紝鎴戜滑鏉ョ湅鐪嬪叿鏈夐€氱敤鎬т笖鏇村姞浼橀泤鐨?Generator 寮傛瑙e喅鏂规锛?/p>
function co(gen) {
return new Promise((resolve, reject) => {
const g = gen();
function next(param) {
const { done, value } = g.next(param);
if (!done) {
// 鏈畬鎴?缁х画閫掑綊
Promise.resolve(value).then((res) => next(res));
} else {
// 瀹屾垚鐩存帴閲嶇疆 Promise 鐘舵€?
resolve(value);
}
}
next();
});
}
co(readFile).then((res) => console.log(res));
鎴戜滑瀹氫箟浜嗕竴涓?co 鍑芥暟鏉ュ寘瑁逛紶鍏ョ殑 generator 鐢熸垚鍣ㄥ嚱鏁般€?/p>
鍦ㄥ嚱鏁?co 涓紝鎴戜滑杩斿洖浜嗕竴涓?Promise 鏉ヤ綔涓哄寘瑁瑰嚱鏁扮殑杩斿洖鍊硷紝鍚屾椂棣栨璋冪敤 co 鍑芥暟鏃朵細璋冪敤 gen() 寰楀埌瀵瑰簲鐨勭敓鎴愬櫒瀵硅薄銆?/p>
涔嬪悗鎴戜滑瀹氫箟浜嗕竴娆?next 鏂规硶锛屽湪 next 鍑芥暟鍐呴儴鍙杩唬鍣ㄦ湭瀹屾垚閭d箞姝ゆ椂鎴戜滑灏变細鍦?value 鐨?then 鏂规硶涓湪姝ら€掑綊璋冪敤璇?next 鍑芥暟銆?/p>
鍏跺疄鍏充簬寮傛杩唬鏃讹紝澶у鏁版儏鍐典笅閮藉彲浠ヤ娇鐢ㄧ被浼艰鍑芥暟涓殑閫掑綊鏂瑰紡鏉ュ鐞嗐€?/h6>
鍑芥暟涓◢寰湁涓夌偣闇€瑕佸ぇ瀹堕澶栨敞鎰忥細
棣栧厛鎴戜滑鍙互鐪嬪埌 next 鍑芥暟鎺ュ彈浼犲叆鐨勪竴涓?param 鐨勫弬鏁般€?br> 杩欐槸鍥犱负鎴戜滑浣跨敤 Generator 鏉ュ鐞嗗紓姝ラ棶棰樻椂锛岄€氳繃
const a = yield promise
灏?promise 鐨?resolve 鍊间氦缁?a 锛屾墍浠ユ垜浠渶瑕佸湪姣忔 then 鍑芥暟涓皢 res 浼犻€掔粰涓嬩竴娆$殑next(res)
浣滀负涓婃 yield 鐨勮繑鍥炲€笺€?/p>鍏舵锛岀粏蹇冪殑鍚屽鍙互鐣欐剰鍒拌繖涓€鍙ヤ唬鐮?code>Promise.resolve(value).then((res) => next(res));銆?br> 鎴戜滑浣跨敤
Promise.resolve
灏?value 杩涜浜嗕竴灞傚寘瑁癸紝杩欐槸鍥犱负褰撶敓鎴愬櫒鍑芥暟涓殑 yield 鏂规硶鍚庣揣鎸ㄧ殑骞朵笉鏄?Promise 鏃讹紝姝ゆ椂鎴戜滑闇€瑕佺粺涓€褰撲綔 Promise 鏉ュ鐞嗭紝鍥犱负鎴戜滑闇€瑕佺粺涓€璋冪敤.then
鏂规硶銆?/p>鏈€鍚庯紝棣栨璋冪敤
next()
鏂规硶鏃讹紝鎴戜滑骞舵病鏈変紶鍏?param 鍙傛暟銆?br> 鐩镐俊杩欎釜骞朵笉闅剧悊瑙o紝褰撴垜浠笉浼犲叆 param 鏃剁浉褰撲簬鐩存帴璋冪敤g.next()
锛屼笂杈规垜浠彁鍒拌繃褰撹皟鐢ㄧ敓鎴愬櫒瀵硅薄鐨?next 鏂规硶浼犲叆鍙傛暟鏃讹紝璇ュ弬鏁颁細褰撲綔涓婁竴娆?yield 璇彞鐨勮繑鍥炲€兼潵澶勭悊銆?/p>
鍥犱负棣栨璋冪敤 g.next()
鏃讹紝鐢熸垚鍣ㄥ嚱鏁板唴閮ㄤ箣鍓嶅苟涓嶅瓨鍦?yield 锛屾墍浠ヤ紶鍏ュ弬鏁版槸娌℃湁浠讳綍鎰忎箟鐨勩€?/p>
瀹冪湅鏉ュ苟涓嶆槸寰堥毦瀵瑰惂锛屼絾鏄€氳繃杩欎竴灏忔浠g爜璁╂垜浠殑 Generator 鎷ユ湁浜嗗彲浠ヨ寮傛浠g爜鍚屾璋冪敤鐨勪功鍐欐柟寮忔潵浣跨敤銆?/p>
鍏跺疄杩欎竴灏忔浠g爜涔熸槸鎵€璋?co[5]
搴撶殑鏍稿績鍘熺悊锛屽綋鐒舵墍璋?co 杩滆繙涓嶆杩欎簺锛屼絾鏄繖娈典唬鐮佽冻澶熸垜浠簡瑙f墍璋撳湪 Async/Await 鏈嚭鐜颁箣鍓嶆垜浠槸濡備綍浣跨敤鎵€璋撶殑 Generator 鏉ヤ綔涓虹粓鏋佸紓姝ヨВ鍐虫柟妗堜簡銆?/p>
Async/Await
閾哄灚浜嗚繖涔堜箙缁堜簬鏉ュ埌鐜伴樁娈?JavaScript 瑙e喅寮傛鐨勬渶缁堟柟妗堜簡銆?/p>
鍦ㄥ墠杈规垜浠亰鍒拌繃鎵€璋?Generator 鐨勫熀纭€鐢ㄦ硶浠ュ強 Babel 鏄浣曞湪 EcmaScript 5 涓娇鐢?Generator 鐢熸垚鍣ㄣ€?/p>
鍚屾椂鎴戜滑椤哄甫鑱婁簡涓嬶紝鍦?Async 娌℃湁鍑虹幇涔嬪墠鎴戜滑濡備綍浣跨敤 Generator 缁撳悎 Promise 鏉ュ鐞嗗紓姝ラ棶棰樸€?/p>
铏界劧涔嬪墠鐨勫紓姝ヨ皟鐢ㄦ柟寮忕湅璧锋潵宸茬粡闈炲父绫讳技浜?async 璇硶浜嗭細
function* readFile() {
const value = yield promise1();
const result = yield promise2(value);
return result;
}
浣嗘槸鍦ㄤ娇鐢?readFile 鏃讹紝鎴戜滑浠嶇劧闇€瑕佷娇鐢?co 鍑芥暟鏉ュ皢 Generator 鏉ュ崟鐙鐞嗕竴灞傦細
co(readFile).then((res) => console.log(res));
閭d箞姝ゆ椂锛宎sync 鐨勫嚭鐜拌В鍐充簡杩欎竴闂锛岀収鏃э紝鎴戜滑鍏堟潵鐪嬬湅鍦ㄤ笉鏀寔 async 璇硶鐨勪綆鐗堟湰娴忚鍣ㄤ笅 Babel 鏄浣曞鐞嗗畠鐨勶細
涔嶄竴鐪嬪彲鑳戒俊鎭湁鐐瑰锛屽埆鎷呭績銆傚叾瀹炶繖浜涢兘鏄垜浠箣鍓嶅垎鏋愮敋鑷冲疄鐜拌繃鐨勪唬鐮併€?/p>
鍦ㄦ繁鍏ヨ繖娈典唬鐮佷箣鍓嶏紝鎴戝厛鍛婅瘔浣犳墍璋?Async 璇硶鏄浣曡瀹炵幇鐨勭粨璁猴細
鍦ㄨ繖涔嬪墠锛屾垜浠€氳繃 Generator 鍜?Promise 瑙e喅寮傛闂鏃讹紝闇€瑕佸皢 Generator 鍑芥暟棰濆浣跨敤 co 鏉ュ寘瑁逛竴灞備粠鑰屽疄鐜扮被浼煎悓姝ョ殑寮傛鍑芥暟璋冪敤銆?/p>
閭d箞濡傛灉鎴戜滑鎯宠瀹炵幇浣庣増鏈祻瑙堝櫒涓嬬殑 Async 璇硶锛岄偅涔堟垜浠皢 co 鍑芥暟浼撮殢 Generator 鐨?polyfill 涓€璧风紪璇戝嚭鏉ヤ笉灏卞彲浠ヤ簡鍚楋紵
鎵€璋?Async 鍏跺疄灏辨槸灏?Generator 鍖呰9浜嗕竴灞?co 鍑芥暟锛屾墍浠ュ畠琚О涓?Generator 鍜?Promise 鐨勮娉曠硸銆?/h6>
鎺ヤ笅鏉ユ垜浠竴璧锋潵鐪嬬湅鍙宠竟鐨?polyfil 瀹炵幇銆?/p>
杩欐鍑芥暟鏄笉鏄緢鐪肩啛锛屾垜浠湪涔嬪墠绠€鍗曡亰杩囧叧浜庡畠鐨勫疄鐜板師鐞嗐€?/p>
鍞竴鏈変竴鐐逛笉鍚岀殑鏄紝瀹冨皢 Generator 鐨勫疄鐜伴澶栧寘瑁逛簡涓€灞?_asyncToGenerator 鍑芥暟杩涜杩斿洖銆?/p>
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
}
_next(undefined);
});
};
}
鏉ョ湅鐪嬫墍璋撶殑 _asyncToGenerator 鍑芥暟锛屽畠鍐呴儴鎺ュ彈涓€涓紶鍏ョ殑 fn 鍑芥暟銆傝繖涓?fn 姝f槸鎵€璋撶殑 Generator 鍑芥暟銆?/p>
褰撹皟鐢?hello() 鏃讹紝瀹炶川涓婃渶缁堢浉褰撲簬璋冪敤 _asyncToGenerator 鍐呴儴鐨勮繑鍥炲嚱鏁帮紝瀹冧細杩斿洖涓€涓?Promise銆?/p>
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
}
_next(undefined);
});
棣栧厛 Promise 涓細杩涜锛?/p>
var gen = fn.apply(self, args);
瀹冧細璋冪敤鎴戜滑浼犲叆鐨?fn锛堢敓鎴愬櫒鍑芥暟锛?杩斿洖鐢熸垚鍣ㄥ璞★紝涔嬪悗瀹冨畾涔変簡涓や釜鏂规硶锛?/p>
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
}
杩欎袱涓柟娉曞唴閮ㄩ兘鍩轰簬 asyncGeneratorStep 鏉ヨ繘琛屽嚱鏁拌皟鐢細
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
鎵€璋?asyncGeneratorStep 鍏跺疄浣犲畬鍏ㄥ彲浠ュ皢瀹冨綋浣滄垜浠箣鍓嶅疄鐜扮殑寮傛瑙e喅鏂规 co 鐨勫師鐞嗭紝瀹冧滑鍐呴儴鐨勬€濇兂鍜屽疄鐜版槸瀹屽叏涓€鑷寸殑锛屽敮涓€鐨勫尯鍒氨鏄繖閲?Babel 缂栬瘧鍚庣殑瀹炵幇鑰冭檻浜?error 鎯呭喌鑰屾垜浠綋鏃跺苟娌℃湁鑰冭檻鍑虹幇閿欒鏃剁殑鎯呭喌銆?/p>
鏈川涓婅繕鏄埄鐢?Generator 鍑芥暟鍐呴儴鍙互琚殏鍋滄墽琛岀殑鐗规€х粨鍚?Promise.prototype.then 涓繘琛岄€掑綊璋冪敤浠庤€屽疄鐜?Async 鐨勮娉曠硸銆?/p>
鍏跺疄鐪嬪埌杩欓噷锛岀粡杩囧墠杈圭煡璇嗙偣鐨勯摵鍨垜鐩镐俊鏈€缁?Async/Await 鐨勫疄鐜板師鐞嗗浣犳潵璇翠竴鐐归兘涓嶄細闄岀敓銆?/p>
涔嬫墍浠ヨ绉颁负璇硶绯栧洜涓烘湰璐ㄤ笂瀹冧篃骞舵病鏈変换浣曢拡瀵逛簬 Generator 鐢熸垚鍣ㄥ嚱鏁板拰 Promise 鐨勫叾浠栫煡璇嗘嫇灞曠偣锛屾伆鎭版槸鏇村ソ鐨勭粨鍚堜簡杩欎袱绉嶈娉曠殑鐗圭偣琛嶇敓鍑轰簡鏇村姞浼橀泤绠€鍗曠殑寮傛瑙e喅鏂规銆?/p>
缁撳熬
鏂囩珷鐨勭粨灏撅紝棣栧厛鎰熻阿姣忎竴涓彲浠ヨ鍒拌繖閲岀殑鏈嬪弸銆?/p>
鎴戜滑璁茶堪浜嗕粠 Generator 鍑芥暟鍙戝睍鍒?Async/Await 鐨勫紓姝ヨВ鍐虫柟妗堜互鍙婂畠浠槸濡備綍鍦ㄤ綆鐗堟湰娴忚鍣ㄤ腑鐨?polyfill 鏈€缁堝欢浼稿埌瀹冧滑鐨勫疄鐜板師鐞嗐€?/p>
鍙傝€冭祫鏂?br> [1]Babel Generator Demo: https://babeljs.io/repl#?browsers=ie 11&build=&builtIns=usage&corejs=3.6&spec=false&loose=false&code_lz=GYVwdgxgLglg9mAVAAgOYFMwAoCUyDeAUMshAgM5TICGyAvMgJ4zoA2AJsgIwDcxpFOK3QA6VnFRZqAGmQByKAAsY5ZCppycfEmTCVkAI3pMWHZACZtAvUNHjJB2QuWr1BzVd36Ix5m04AzJ6CwmISWBBOSurqEB6EAL6EhMJUqMYY2FrJqCJg6AAeULg8yAD0ZQTIAG7UrCDoAFzcsuwITcjAdeToyEm5-UVYcgAO1ABO1AC2ALTUHuWV-DV1Dc3mre3NXaw9fYQDhcWjE9Mz7ngVVbX1HQGb-dvdvUlAA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=env,stage-0,stage-1,stage-2,stage-3&prettier=false&targets=&version=7.17.5&externalPlugins=&assumptions={}
[2]polyfill: https://developer.mozilla.org/zh-CN/docs/Glossary/Polyfill
[3]杩唬鍣ㄥ崗璁? https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols
[4]facebook/regenerator: https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js
[5]co: https://github.com/tj/co