co模塊的前端實現

其實就是照着網上的介紹和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;
}));
相關文章
相關標籤/搜索