第六章 自定义 Promise
1 定义整体结构
/**
* 自定义 Promise
*/
(function(window){
/**
* Promise 构造函数
* @param {Function} executor - 执行器函数 (resolve,reject) => {}
*/
function Promise(executor) {
}
/**
* 为 Promise 指定回调函数
* @param {Function} onResolved - 成功的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
Promise.prototype.then = function(onResolved, onRejected) {
}
/**
* 为Promise 指定失败的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
Promise.prototype.catch = function(onRejected) {
}
/**
* 返回一个指定了成功 value 的 Promise 实例
* @param {Mixed} value - 成功的值
* @return {Promise} 返回一个 Promise 实例
*/
Promise.resolve = function(value){
}
/**
* 返回一个指定了失败 reason 的 Promise 实例
* @param {Mixed} reason - 失败的 reason
* @return {Promise} 返回一个 Promise 实例
*/
Promise.reject = function(reason){
}
/**
* 返回一个 Promise 实例,只有 promises 所有的都成功时,才最终成功,只有一个失败直接失败
* @param {array} promises - 由 Promise 实例组成的数组
* @return {Promise} 返回一个 Promise 实例
*/
Promise.all = function(promises) {
}
/**
* 返回一个 Promise 实例,一旦某个 Promise 实例成功或失败,返回的 Promise 实例也成功或失败。
* @param {Iterator} promises - 由 Promise 实例组成的数组或实现 Interator 接口的类型
* @return {Promise} 返回一个 Promise 实例
*/
Promise.race = function(promises) {
}
// 暴露构造函数
window.Promise = Promise;
})(window);
2 Promise 构造函数的实现
/**
* Promise 构造函数
* @param {Function} executor - 执行器函数 (resolve,reject) => {}
*/
function Promise(executor) {
var self = this; //保存 this
self.status = 'pending'; // 初始状态值,成功了变为 resolved,失败了变为 rejected
self.data = undefined; // 保存成功的 value 或失败的 reason
self.callbacks = []; // 保存所有待调用的包含 onResolved 和 onRejected 回调函数的对象的数组
// 同步调用 executor, 出现异常直接失败
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
/**
* 调用该函数可以将状态改为成功
* @param {*} value 成功的值
*/
function resolve(value) {
// 如果当前不是 pending,直接结束。确保状态只能改变一次
if (self.status !== 'pending') {
return;
}
// 更新状态和值
self.status = 'resolved';
self.data = value;
// 异步调用所有待处理的 onResolved 成功回调函数
setTimeout(function() {
self.callbacks.forEach(function(obj){
obj.onResolved(value)
})
})
}
/**
* 调用该函数可以将状态改为失败
* @param {*} reason 失败的 reason
*/
function reject(reason) {
// 如果当前不是 pending,直接结束。确保状态只能改变一次
if (self.status !== 'pending') {
return;
}
// 更新状态和值
self.status = 'rejected';
self.data = reason;
// 异步调用所有待处理的 onRejected 回调函数
setTimeout(function(){
self.callbacks.forEach(function(obj) {
obj.onResolved(reason);
})
})
}
}
3 Promise.prototype.then() / catch() 的实现
/**
* 为 Promise 指定回调函数
* @param {Function} onResolved - 成功的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
Promise.prototype.then = function(onResolved, onRejected) {
var self = this; // 保存 this
// 如果 onResolved 或者 onRejected 不是函数,给它制定一个默认的函数
onResolved = typeof onResolved === 'function' ? onResolved : function(value){ return value;};
onRejected = typeof onRejected === 'function' ? onRejected : function(reason) { throw reason};
// 返回 一个 Promise
return new Promise(function(resolve, reject) {
// 如果状态是 resolved, 添加回调的时候状态已经改变
if (self.status === 'resolved') {
setTimeout(function(){
handler(onResolved);
})
}
// 如果状态是 rejected,添加回调的时候状态已经改变
if (self.status === 'rejected') {
setTimeout(function(){
handler(onRejected);
})
}
// 添加回调的时候状态还未改变
if (self.status === 'pending') {
// 添加回调函数到数组 并且 确保拿到回调函数的返回值
self.callbacks.push({
onResolved: function(){
handler(onResolved);
},
onRejected: function(){
handler(onRejected);
}
});
}
// 封装函数,用来在不同的状态下执行回调函数
function handler(callback) {
try {
// 执行 then 的回调函数
var result = callback(self.data);
// 判断 then 回调函数返回结果
// 如果是个 promise,把成功的值或者错误的原因传出去
if (result instanceof Promise) {
result.then(function(value){
resolve(value);
}, function(reason){
reject(reason);
});
} else {
resolve(result)
}
} catch (error) {
reject(error);
}
}
});
}
/**
* 为Promise 指定失败的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
}
4 Promise.resolve() / reject() 的实现
/**
* 返回一个指定了成功 value 的 Promise 实例
* @param {Mixed} value - 成功的值
* @return {Promise} 返回一个 Promise 实例
*/
Promise.resolve = function(value){
// 返回 Promise 对象
return new Promise(function(resolve, reject){
// 判断value是Promise、thenable 对象或者其他
if (value instanceof Promise || (value !== undefined && value !== null && typeof value.then === 'function')) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
/**
* 返回一个指定了失败 reason 的 Promise 实例
* @param {Mixed} reason - 失败的 reason
* @return {Promise} Promise 实例
*/
Promise.reject = function(reason){
return new Promise(function(resolve, reject){
reject(reason);
})
}
5 Promise.all() / race() 的实现
/**
* 返回一个 Promise 实例,只有 promises 所有的都成功时,才最终成功,只有一个失败直接失败
* @param {array} promises - 由 Promise 实例组成的数组
* @return {Promise} 返回一个 Promise 实例
*/
Promise.all = function(promises) {
// 保存返回的 promise 的值
var promiseValues = [];
// 标记变量,没循环一次 +1
var flag = 0;
// 返回Promise 对象
return new Promise(function(resolve, reject){
for (var i = 0; i < promises.length; i ++) {
promises[i].then(function(value){
promiseValues.push(value); // 把value加入数组
flag ++; // 标志位自增
// 如果标志位等于数组长度,说明都成功了
if (flag === promises.length) {
resolve(promiseValues);
}
}, function(reason){
// 如果一个 promise 失败all就返回失败的
reject(reason);
})
}
});
}
/**
* 返回一个 Promise 实例,一旦某个 Promise 实例成功或失败,返回的 Promise 实例也成功或失败。
* @param {Iterator} promises - 由 Promise 实例组成的数组或实现 Interator 接口的类型
* @return {Promise} 返回一个 Promise 实例
*/
Promise.race = function(promises) {
// 返回Promise 对象
// 那个promise 先返回,就遵照哪一个
return new Promise(function(resolve, reject){
for (var i = 0; i < promises.length; i ++) {
promises[i].then(resolve, reject);
}
})
}
6 Promise.resolveDelay() / rejectDelay() 的实现
注意:原生Promsie 并没有这两个方法。
resolveDelay() 返回一个延迟指定时间才变为成功状态的 Promise 对象。
rejectDelay() 返回一个延迟指定时间才失败的 Promise 对象。
/**
* 指定时间才能完成的 Promise
* @param {*} value resolved 状态的值,如果是Promise对象遵循其状态,否则当value
* @param {number} time 时间毫秒数
* @return {Promise}
*/
Promise.resolveDelay = function(value, time){
return new Promise(function(resolve, reject){
//定时器
setTimeout(function(){
// 判断 value 是否是promise 对象
if (value instanceof Promise || (value !== undefined && value !== null && typeof value.then === 'function')) {
value.then(resolve, reject);
} else {
resolve(value);
}
}, time);
})
}
/**
* 指定延迟时间返回失败状态的 Promise
* @param {*} reason 失败的原因,该参数只作为失败状态原因
* @param {number} time 时间毫秒数
* @return {Promise}
*/
Promise.rejectDelay = function(value, time){
return new Promise(function(resolve, reject){
//定时器
setTimeout(function(){
reject(value);
}, time)
})
}
7 ES5 function 完整版本
/**
* 自定义 Promise
*/
(function(window){
/**
* Promise 构造函数
* @param {Function} executor - 执行器函数 (resolve,reject) => {}
*/
function Promise(executor) {
var self = this; //保存 this
self.status = 'pending'; // 初始状态值,成功了变为 resolved,失败了变为 rejected
self.data = undefined; // 保存成功的 value 或失败的 reason
self.callbacks = []; // 保存所有待调用的包含 onResolved 和 onRejected 回调函数的对象的数组
// 同步调用 executor, 出现异常直接失败
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
/**
* 调用该函数可以将状态改为成功
* @param {*} value 成功的值
*/
function resolve(value) {
// 如果当前不是 pending,直接结束。确保状态只能改变一次
if (self.status !== 'pending') {
return;
}
// 更新状态和值
self.status = 'resolved';
self.data = value;
// 异步调用所有待处理的 onResolved 成功回调函数
setTimeout(function() {
self.callbacks.forEach(function(obj){
obj.onResolved(value)
})
})
}
/**
* 调用该函数可以将状态改为失败
* @param {*} reason 失败的 reason
*/
function reject(reason) {
// 如果当前不是 pending,直接结束。确保状态只能改变一次
if (self.status !== 'pending') {
return;
}
// 更新状态和值
self.status = 'rejected';
self.data = reason;
// 异步调用所有待处理的 onRejected 回调函数
setTimeout(function(){
self.callbacks.forEach(function(obj) {
obj.onRejected(reason);
})
})
}
}
/**
* 为 Promise 指定回调函数
* @param {Function} onResolved - 成功的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
Promise.prototype.then = function(onResolved, onRejected) {
var self = this; // 保存 this
// 如果 onResolved 或者 onRejected 不是函数,给它制定一个默认的函数
onResolved = typeof onResolved === 'function' ? onResolved : function(value){ return value;};
onRejected = typeof onRejected === 'function' ? onRejected : function(reason) { throw reason};
// 返回 一个 Promise
return new Promise(function(resolve, reject) {
// 如果状态是 resolved, 添加回调的时候状态已经改变
if (self.status === 'resolved') {
setTimeout(function(){
handler(onResolved);
})
}
// 如果状态是 rejected,添加回调的时候状态已经改变
if (self.status === 'rejected') {
setTimeout(function(){
handler(onRejected);
})
}
// 添加回调的时候状态还未改变
if (self.status === 'pending') {
// 添加回调函数到数组 并且 确保拿到回调函数的返回值
self.callbacks.push({
onResolved: function(){
handler(onResolved);
},
onRejected: function(){
handler(onRejected);
}
});
}
// 封装函数,用来在不同的状态下执行回调函数
function handler(callback) {
try {
// 执行 then 的回调函数
var result = callback(self.data);
// 判断 then 回调函数返回结果
// 如果是个 promise,把成功的值或者错误的原因传出去
if (result instanceof Promise) {
result.then(function(value){
resolve(value);
}, function(reason){
reject(reason);
});
} else {
resolve(result)
}
} catch (error) {
reject(error);
}
}
});
}
/**
* 为Promise 指定失败的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
}
/**
* 返回一个指定了成功 value 的 Promise 实例
* @param {Mixed} value - 成功的值
* @return {Promise} 返回一个 Promise 实例
*/
Promise.resolve = function(value){
// 返回 Promise 对象
return new Promise(function(resolve, reject){
// 判断value是Promise、thenable 对象或者其他
if (value instanceof Promise || (value !== undefined && value !== null && typeof value.then === 'function')) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
/**
* 返回一个指定了失败 reason 的 Promise 实例
* @param {Mixed} reason - 失败的 reason
* @return {Promise} Promise 实例
*/
Promise.reject = function(reason){
return new Promise(function(resolve, reject){
reject(reason);
})
}
/**
* 返回一个 Promise 实例,只有 promises 所有的都成功时,才最终成功,只有一个失败直接失败
* @param {array} promises - 由 Promise 实例组成的数组
* @return {Promise} 返回一个 Promise 实例
*/
Promise.all = function(promises) {
// 保存返回的 promise 的值
var promiseValues = [];
// 标记变量,没循环一次 +1
var flag = 0;
// 返回Promise 对象
return new Promise(function(resolve, reject){
for (var i = 0; i < promises.length; i ++) {
promises[i].then(function(value){
promiseValues.push(value); // 把value加入数组
flag ++; // 标志位自增
// 如果标志位等于数组长度,说明都成功了
if (flag === promises.length) {
resolve(promiseValues);
}
}, function(reason){
// 如果一个 promise 失败all就返回失败的
reject(reason);
})
}
});
}
/**
* 返回一个 Promise 实例,一旦某个 Promise 实例成功或失败,返回的 Promise 实例也成功或失败。
* @param {Iterator} promises - 由 Promise 实例组成的数组或实现 Interator 接口的类型
* @return {Promise} 返回一个 Promise 实例
*/
Promise.race = function(promises) {
// 返回Promise 对象
// 那个promise 先返回,就遵照哪一个
return new Promise(function(resolve, reject){
for (var i = 0; i < promises.length; i ++) {
promises[i].then(resolve, reject);
}
})
}
/**
* 指定时间才能完成的 Promise
* @param {*} value resolved 状态的值,如果是Promise对象遵循其状态,否则当value
* @param {number} time 时间毫秒数
* @return {Promise}
*/
Promise.resolveDelay = function(value, time){
return new Promise(function(resolve, reject){
//定时器
setTimeout(function(){
// 判断 value 是否是promise 对象
if (value instanceof Promise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}, time);
})
}
/**
* 指定延迟时间返回失败状态的 Promise
* @param {*} reason 失败的原因,该参数只作为失败状态原因
* @param {number} time 时间毫秒数
* @return {Promise}
*/
Promise.rejectDelay = function(value, time){
return new Promise(function(resolve, reject){
//定时器
setTimeout(function(){
reject(value);
}, time)
})
}
// 暴露构造函数
window.Promise = Promise;
})(window);
8 ES6 class 完整版本
/**
* 自定义 Promise
*/
(function(window){
/**
* 定义 Promise 类
*/
class Promise {
/**
* Promise 构造函数
* @param {Function} executor - 执行器函数 (resolve,reject) => {}
*/
constructor(executor) {
var self = this; //保存 this
self.status = 'pending'; // 初始状态值,成功了变为 resolved,失败了变为 rejected
self.data = undefined; // 保存成功的 value 或失败的 reason
self.callbacks = []; // 保存所有待调用的包含 onResolved 和 onRejected 回调函数的对象的数组
// 同步调用 executor, 出现异常直接失败
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
/**
* 调用该函数可以将状态改为成功
* @param {*} value 成功的值
*/
function resolve(value) {
// 如果当前不是 pending,直接结束。确保状态只能改变一次
if (self.status !== 'pending') {
return;
}
// 更新状态和值
self.status = 'resolved';
self.data = value;
// 异步调用所有待处理的 onResolved 成功回调函数
setTimeout(function() {
self.callbacks.forEach(function(obj){
obj.onResolved(value)
})
})
}
/**
* 调用该函数可以将状态改为失败
* @param {*} reason 失败的 reason
*/
function reject(reason) {
// 如果当前不是 pending,直接结束。确保状态只能改变一次
if (self.status !== 'pending') {
return;
}
// 更新状态和值
self.status = 'rejected';
self.data = reason;
// 异步调用所有待处理的 onRejected 回调函数
setTimeout(function(){
self.callbacks.forEach(function(obj) {
obj.onRejected(reason);
})
})
}
}
/**
* 为 Promise 指定回调函数
* @param {Function} onResolved - 成功的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
then(onResolved, onRejected) {
var self = this; // 保存 this
// 如果 onResolved 或者 onRejected 不是函数,给它制定一个默认的函数
onResolved = typeof onResolved === 'function' ? onResolved : function(value){ return value;};
onRejected = typeof onRejected === 'function' ? onRejected : function(reason) { throw reason};
// 返回 一个 Promise
return new Promise(function(resolve, reject) {
// 如果状态是 resolved, 添加回调的时候状态已经改变
if (self.status === 'resolved') {
setTimeout(function(){
handler(onResolved);
})
}
// 如果状态是 rejected,添加回调的时候状态已经改变
if (self.status === 'rejected') {
setTimeout(function(){
handler(onRejected);
})
}
// 添加回调的时候状态还未改变
if (self.status === 'pending') {
// 添加回调函数到数组 并且 确保拿到回调函数的返回值
self.callbacks.push({
onResolved: function(){
handler(onResolved);
},
onRejected: function(){
handler(onRejected);
}
});
}
// 封装函数,用来在不同的状态下执行回调函数
function handler(callback) {
try {
// 执行 then 的回调函数
var result = callback(self.data);
// 判断 then 回调函数返回结果
// 如果是个 promise,把成功的值或者错误的原因传出去
if (result instanceof Promise) {
result.then(function(value){
resolve(value);
}, function(reason){
reject(reason);
});
} else {
resolve(result)
}
} catch (error) {
reject(error);
}
}
});
}
/**
* 为Promise 指定失败的回调函数
* @param {Function} onRejected - 失败的回调函数
* @return {Promise} 返回一个新的 Promise 实例
*/
catch(onRejected) {
return this.then(undefined, onRejected);
}
/**
* 返回一个指定了成功 value 的 Promise 实例
* @param {Mixed} value - 成功的值
* @return {Promise} 返回一个 Promise 实例
*/
static resolve(value){
// 返回 Promise 对象
return new Promise(function(resolve, reject){
// 判断value是Promise、thenable 对象或者其他
if (value instanceof Promise || (value !== undefined && value !== null && typeof value.then === 'function')) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
}
/**
* 返回一个指定了失败 reason 的 Promise 实例
* @param {Mixed} reason - 失败的 reason
* @return {Promise} Promise 实例
*/
static reject(reason){
return new Promise(function(resolve, reject){
reject(reason);
})
}
/**
* 返回一个 Promise 实例,只有 promises 所有的都成功时,才最终成功,只有一个失败直接失败
* @param {array} promises - 由 Promise 实例组成的数组
* @return {Promise} 返回一个 Promise 实例
*/
static all(promises) {
// 保存返回的 promise 的值
var promiseValues = [];
// 标记变量,没循环一次 +1
var flag = 0;
// 返回Promise 对象
return new Promise(function(resolve, reject){
for (var i = 0; i < promises.length; i ++) {
promises[i].then(function(value){
promiseValues.push(value); // 把value加入数组
flag ++; // 标志位自增
// 如果标志位等于数组长度,说明都成功了
if (flag === promises.length) {
resolve(promiseValues);
}
}, function(reason){
// 如果一个 promise 失败all就返回失败的
reject(reason);
})
}
});
}
/**
* 返回一个 Promise 实例,一旦某个 Promise 实例成功或失败,返回的 Promise 实例也成功或失败。
* @param {Iterator} promises - 由 Promise 实例组成的数组或实现 Interator 接口的类型
* @return {Promise} 返回一个 Promise 实例
*/
static race(promises) {
// 返回Promise 对象
// 那个promise 先返回,就遵照哪一个
return new Promise(function(resolve, reject){
for (var i = 0; i < promises.length; i ++) {
promises[i].then(resolve, reject);
}
})
}
/**
* 指定时间才能完成的 Promise
* @param {*} value resolved 状态的值,如果是Promise对象遵循其状态,否则当value
* @param {number} time 时间毫秒数
* @return {Promise}
*/
static resolveDelay(value, time){
return new Promise(function(resolve, reject){
//定时器
setTimeout(function(){
// 判断 value 是否是promise 对象
if (value instanceof Promise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}, time);
})
}
/**
* 指定延迟时间返回失败状态的 Promise
* @param {*} reason 失败的原因,该参数只作为失败状态原因
* @param {number} time 时间毫秒数
* @return {Promise}
*/
static rejectDelay(value, time){
return new Promise(function(resolve, reject){
//定时器
setTimeout(function(){
reject(value);
}, time)
})
}
}
// 暴露构造函数
window.Promise = Promise;
})(window);