其實就是照着網上的介紹和co的源碼實現了一個本身用的前端async模塊。支持RequireJS和SeaJS,支持$.ajax。
有喜歡co可是不知道怎麼用的前端朋友能夠拿去用。前端
co模塊的意義和原理在sf上已經有詳細的介紹了,具體參見:
http://segmentfault.com/a/1190000002732081ajax
用法:segmentfault
async(function* () { var a = yield Promise.resolve(1); console.log(a); var b = yield [Promise.resolve(2), Promise.resolve(3)]; console.log(b); return 4; }).then(function (value) { console.log(value); }).catch(function (e) { // 異常處理 }); // 輸出結果應該爲 1 [2,3] 4
源碼:數組
/*global exports*/ 'use strict'; (function (factory) { // 各類模塊加載方式的處理 if (typeof define === 'function' && define.amd) { define([], factory); } else if (typeof define === 'function' && define.cmd) { define(function (require, exports, module) { module.exports = factory(jQuery); }); } else if (typeof exports === 'object') { exports.async = factory(); } else { // window.async=factory(); } }(function () { // 下面這倆函數是有用的 function async(generator) { // 主Promise return new Promise(function (resolve, reject) { var g = generator(); /** * 該函數會在異步過程執行完畢後被調用,會喚醒主函數繼續執行到下一個yield或return爲止。 * 參數val爲異步過程的結果,即promise.result。 * 返回值爲主函數內yield或return的結果, * 若是是yield則必須爲promise或可被autoPack包裝的對象,或者包含前二者的數組 */ function next(val) { // 將上次運行結果返回給主函數,令主函數繼續執行到下一處中斷,並將結果存入result var result = g.next(val); // 暫存主函數運行結果 var promise = result.value; // 判斷主函數是否執行完畢,執行完畢則調用resolve完成主Promise,不然繼續執行 if (!result.done) { // 判斷主函數提供的參數是否爲數組, // 若是不是數組則用autoPack封裝後經過then(next)綁定下一步流程。並經過catch(reject)拋出異常 // 若是是數組則對每一個成員進行封裝後用Promise.All打包,而後繼續執行。 if (promise instanceof Array) { Promise.all(promise.map(autoPack)).then(next).catch(reject); } else { autoPack(promise).then(next).catch(reject); } } else { resolve(promise); } } // 捕獲並經過reject拋出異常 try { next(); } catch (e) { reject(e); } }) } // 自動打包,能夠將第三方實現的Promise工具打包爲ES6標準的Promise // 目前僅支持jQuery.Promise function autoPack(target) { // 包裝$.ajax if (target.error) { return new Promise(function (resolve, reject) { target.done(resolve).error(reject); }) } else { return target; } } return async; }));