实在就是照着网上的引见和co的源码完成了一个本身用的前端async模块。支撑RequireJS和SeaJS,支撑$.ajax。
有喜好co然则不知道怎样用的前端朋侪能够拿去用。
co模块的意义和道理在sf上已经有细致的引见了,详细拜见:
http://segmentfault.com/a/1190000002732081
用法:
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;
}));