<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise</title>
</head>
<body>
<script>
(function() {
/**
* 定义自定义promise属性, 属性可写但不可枚举
* 在new阶段调用
*/
function defineNotEnumrableProperty(obj, key, value) {
Object.defineProperty(obj, key, {
value,
enumerable: false,
writable: true
})
}
// 保存每个promise实例的回调,须事先调用generateCacheCbksZone生成
const cacheCbksMap = new Map();
/**
* 生成cache实例回调的对象
* 在new阶段调用
*/
function generateCacheCbksZone(inst) {
if (!cacheCbksMap.has(inst)) {
cacheCbksMap.set(inst, {
resolvedCbks: [],
rejectedCbks: []
})
}
}
/**
* 销毁cache实例回调的对象
* 在rejected或resolved回调执行完毕后调用
*/
function destoryCacheCbksZone(inst) {
if (cacheCbksMap.has(inst)) {
cacheCbksMap.delete(inst);
}
}
/**
* 定义常量
*/
const STATE = {
/* promise的状态 */
PENDING: 'pending',
RESOLVED: 'resolved',
REJECTED: 'rejected'
};
function Promise(excutor) {
// this.resolvedCbks = []; // 保存成功回调
// this.rejectedCbks = []; // 保存失败回调
generateCacheCbksZone(this);
defineNotEnumrableProperty(this, '[[PromiseState]]', STATE.PENDING);
defineNotEnumrableProperty(this, '[[PromiseResult]]', undefined);
function resolve(result) {
if (this['[[PromiseState]]'] === STATE.PENDING) {
// 状态只允许修改一次
this['[[PromiseState]]'] = STATE.RESOLVED;
this['[[PromiseResult]]'] = result;
// setTimeout(() => this.resolvedCbks.forEach(fn => result = fn(result)))
setTimeout(() => {
cacheCbksMap.get(this).resolvedCbks.forEach(fn => result = fn(result))
// 销毁保存回调的数组
destoryCacheCbksZone(this);
})
}
}
function reject(reason) {
if (this['[[PromiseState]]'] === STATE.PENDING) {
// 状态只允许修改一次
this['[[PromiseState]]'] = STATE.REJECTED;
this['[[PromiseResult]]'] = reason;
setTimeout(() => {
const rejectedCbks = cacheCbksMap.get(this).rejectedCbks;
// if (!this.rejectedCbks.length) {
if (!rejectedCbks.length) {
// 若不处理失败结果,则抛出错误
throw new Error(reason);
}
// this.rejectedCbks.forEach(fn => fn(reason))
rejectedCbks.forEach(fn => fn(reason))
// 销毁保存回调的数组
destoryCacheCbksZone(this);
})
}
}
try {
excutor(resolve.bind(this), reject.bind(this)); // 默认传 resolve reject 方法
} catch(e) {
reject.call(this, e);
}
}
/**
* Promise的resolve方法,返回一个状态为resolved的对象
*/
Promise.resolve = function _resolve(result) {
return new Promise(resolve => resolve(result))
}
/**
* Promise的resolve方法,返回一个状态为rejected的对象
*/
Promise.reject = function _reject(result) {
return new Promise((resolve, reject) => reject(result))
}
/**
* Promise的all方法,传入promise实例的集合
*/
Promise.all = function _all(pArray) {
return new Promise((resolve, reject) => {
const resArray = []; // 按顺序保存res
let completedCount = 0; // 记录resolved的promise数量
pArray.forEach((p, i) => {
p.then(
result => {
resArray[i] = result;
completedCount += 1; // 完成数量+1
if (resArray.length === completedCount) {
/**
* completedCount等于resArray的长度时
* 说明所有promise已为resolved状态
* 将返回promise实例的状态改为resolved,result结果为resArray
*/
resolve(resArray);
}
},
reason => reject(reason) // 只要有一个异常,则将返回的promise实例状态改为rejected,失败原因为异常信息
)
})
})
}
/**
* Promise的race方法,传入promise实例的集合
*/
Promise.race = function _race(pArray) {
return new Promise((resolve, reject) => {
// 一旦有结果立马根据结果类型resolve或reject
pArray.forEach((p, i) => p.then(result => resolve(result), reason => reject(reason)))
})
}
const CachePromise = Promise;
{
function Promise() {
defineNotEnumrableProperty(this, 'then', function _then() {
const [onResolved, onRejected] = arguments;
return new CachePromise((resolve, reject) => {
const { resolvedCbks, rejectedCbks } = cacheCbksMap.get(this);
if (onResolved) {
// this.resolvedCbks.push(onResolved, resolve);
resolvedCbks.push(onResolved, resolve);
}
if (onRejected) {
// 有onRejected,则在当前promise实例中处理失败结果
// this.rejectedCbks.push(onRejected, () => resolve());
rejectedCbks.push(onRejected, () => resolve());
} else {
// 无onRejected,则返回一个rejected的Promise实例,在返回的实例上处理失败结果,若不处理则报错
// this.rejectedCbks.push(reject);
rejectedCbks.push(reject);
}
})
})
defineNotEnumrableProperty(this, 'catch', function _catch() {
const onCatch = arguments[0];
return new CachePromise((resolve, reject) => {
if (onCatch) {
// 若有onCatch,则放到rejectedCbks中,处理失败结果后返回一个resolved的Promise实例
this.rejectedCbks.push(onCatch, () => resolve());
}
})
})
defineNotEnumrableProperty(this, 'finally', function _finally() {
const onFinally = arguments[0];
return new CachePromise((resolve, reject) => {
if (onFinally) {
// 若有onFinally,则放到resolvedCbks,rejectedCbks中
this.resolvedCbks.push(() => onFinally(), () => resolve());
this.rejectedCbks.push(() => onFinally(), reject);
}
})
})
}
CachePromise.prototype = new Promise();
}
Promise = CachePromise;
// /**
// * 实例的 then 方法
// */
// Promise.prototype.then = function _then(onResolved, onRejected) {
// return new Promise((resolve, reject) => {
// const { resolvedCbks, rejectedCbks } = cacheCbksMap.get(this);
// if (onResolved) {
// // this.resolvedCbks.push(onResolved, resolve);
// resolvedCbks.push(onResolved, resolve);
// }
// if (onRejected) {
// // 有onRejected,则在当前promi
评论0