promise
- 有三个状态:pending(进行中)、resolved(成功)、rejected(失败)
- 无法取消Promise,一旦新建就会立即执行,无法中途取消
- 当处于Pending状态时,无法得知目前进展到那个阶段
- promise真正执行回调的时候,定义Promise那部分实际上已经走完了,所以Promise的报错堆栈上下文不太友好
generator
- ES6 引入,可以暂停和继续执行函数
- 可以当做一个迭代器(iterator)来用,也可以在内部存一些状态,成为一个状态机
- yield(关键字)表示暂停 yield表单式本身没有返回值或者说总是返回undefined
- next方法可以带一个参数,该参数就会被当做上一个yield的返回值
async
-
async 对应的是 * 。
-
await 对应的是 yield 。
-
async/await 自动进行了 Generator 的流程控制。
co.js
/**
* slice() reference.
*/
var slice = Array.prototype.slice;
/**
* Expose `co`.
*/
module.exports = co['default'] = co.co = co;
/**
* Execute the generator function or a generator
* and return a promise.
*
* @param {Function} fn
* @return {Promise}
* @api public
*/
// 这里是核心代码
function co(gen) {
// 缓存上下文
var ctx = this;
var args = slice.call(arguments, 1)
// we wrap everything in a promise to avoid promise chaining,
// which leads to memory leak errors.
// see https://github.com/tj/co/issues/180
// co() 返回值为 promise
return new Promise(function(resolve, reject) {
// 执行一次 generator 函数以获取遍历器
if (typeof gen === 'function') gen = gen.apply(ctx, args);
if (!gen || typeof gen.next !== 'function') return resolve(gen);
// 启动执行
onFulfilled();
/**
* @param {Mixed} res
* @return {Promise}
* @api private
*/
function onFulfilled(res) {
var ret;
// 执行 generator 函数的 next 方法,如出错则 reject
try {
ret = gen.next(res);
} catch (e) {
return reject(e);
}
// 继续执行 next 函数
next(ret);
}
/**
* @param {Error} err
* @return {Promise}
* @api private
*/
function onRejected(err) {
var ret;
// 执行 generator 函数的 throw 方法(用于抛出错误,由 generator 函数内部进行错误处理),如出错则 reject
try {
ret = gen.throw(err);
} catch (e) {
return reject(e);
}
// 继续执行 next 函数
next(ret);
}
/**
* Get the next value in the generator,
* return a promise.
*
* @param {Object} ret
* @return {Promise}
* @api private
*/
// 关键所在,自动连续执行 next()
function next(ret) {
// generator 函数执行完毕,返回
if (ret.done) return resolve(ret.value);
// 每次均将 yield 返回的 value 转换为 promise
var value = toPromise.call(ctx, ret.value);
// 使用 Promise.then 递归连续执行
// onFulfilled 和 onRejected 函数中会继续调用 next 函数自身
if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
// yield 返回的 value 无法转换为 promise 时进行错误处理
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
+ 'but the following object was passed: "' + String(ret.value) + '"'));
}
});
}
/**
* Wrap the given generator `fn` into a
* function that returns a promise.
* This is a separate function so that
* every `co()` call doesn't create a new,
* unnecessary closure.
*
* @param {GeneratorFunction} fn
* @return {Function}
* @api public
*/
// 单看代码可能略为有点晦涩,结合上面 co.wrap 的使用示例比较容易理解
// 实际上这里只是作了一层简单的封装,方便传参
co.wrap = function (fn) {
createPromise.__generatorFunction__ = fn;
return createPromise;
function createPromise() {
// 传入的参数通过 apply 方式作为 fn 的参数执行
// 然后仍然是调用 co 函数,回到上面的逻辑
return co.call(this, fn.apply(this, arguments));
}
};
// 下面是一些功能性的 utils 函数,根据注释便可知晓其用法,此处省略函数具体实现,不作过多赘述
/**
* Convert a `yield`ed value into a promise.
*/
function toPromise(obj) {}
/**
* Convert a thunk to a promise.
*/
function thunkToPromise(fn) {}
/**
* Convert an array of "yieldables" to a promise.
* Uses `Promise.all()` internally.
*/
function arrayToPromise(obj) {}
/**
* Convert an object of "yieldables" to a promise.
* Uses `Promise.all()` internally.
*/
function objectToPromise(obj){}
/**
* Check if `obj` is a promise.
*/
function isPromise(obj) {}
/**
* Check if `obj` is a generator.
*/
function isGenerator(obj) {}
/**
* Check if `obj` is a generator function.
*/
function isGeneratorFunction(obj) {}
/**
* Check for plain object.
*/
function isObject(val) {}
Promise简单实现
class Promise{
// 构造器
constructor(executor){
// 初始化state为等待态
this.state = 'pending';
// 成功的值
this.value = undefined;
this.reason = undefined;
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放法数组
this.onRejectedCallbacks = [];
// 成功
let resolve = value => {
// state改变,resolve调用就会失败
if (this.state === 'pending') {
// resolve调用后,state转化为成功态
this.state = 'fulfilled';
// 储存成功的值
this.value = value;
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn=>fn());
}
};
// 失败
let reject = reason => {
// state改变,reject调用就会失败
if (this.state === 'pending') {
// reject调用后,state转化为失败态
this.state = 'rejected';
// 储存失败的原因
this.reason = reason;
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach(fn=>fn());
}
};
// 如果executor执行报错,直接执行reject
try{
// 立即执行
executor(resolve, reject);
} catch (err) {
// 捕获执行错误
reject(err);
}
}
// then 方法 有两个参数onFulfilled onRejected
then(onFulfilled,onRejected) {
// onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// onRejected如果不是函数,就忽略onRejected,直接扔出错误
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
// 声明返回的promise2
let promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
//Promises/A+规定onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// resolvePromise函数,处理自己return的promise和默认的promise2的关系
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
if (this.state === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
// 当状态state为pending时
if (this.state === 'pending') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// onRejected传入到失败数组
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
});
};
});
// 返回promise,完成链式
return promise2;
}
catch(fn){
return this.then(null,fn);
}
}
function resolvePromise(promise2, x, resolve, reject){
// 循环引用报错
if(x === promise2){
// reject报错
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 防止多次调用
let called;
// x不是null 且x是对象或者函数
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
// A+规定,声明then = x的then方法
let then = x.then;
// 如果then是函数,就默认是promise了
if (typeof then === 'function') {
// 就让then执行 第一个参数是this 后面是成功的回调 和 失败的回调
then.call(x, y => {
// 成功和失败只能调用一个
if (called) return;
called = true;
// resolve的结果依旧是promise 那就继续解析
resolvePromise(promise2, y, resolve, reject);
}, err => {
// 成功和失败只能调用一个
if (called) return;
called = true;
reject(err);// 失败了就失败了
})
} else {
resolve(x); // 直接成功即可
}
} catch (e) {
// 也属于失败
if (called) return;
called = true;
// 取then出错了那就不要在继续执行了
reject(e);
}
} else {
resolve(x);
}
}