自定义Promise对象案例
2023-05-09 Js 1959
window.onload = function () {
class Promise {
// 定义三个静态属性
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
// 定义构造函数
constructor(executor) {
// 初始化状态为pending
this.state = 'pending';
// 初始化成功值和失败原因
this.value = undefined;
this.reason = undefined;
// 初始化回调函数数组
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
// 定义一个resolve函数,用于改变状态和传递成功值
let resolve = (value) => {
// 只有在pending状态下才能改变状态
if (this.state === 'pending') {
// 改变状态为fulfilled
this.state = 'fulfilled';
// 保存成功值
this.value = value;
// 遍历并执行成功回调数组中的函数
this.onResolvedCallbacks.forEach(fn => fn());
}
};
// 定义一个reject函数,用于改变状态和传递失败原因
let reject = (reason) => {
// 只有在pending状态下才能改变状态
if (this.state === 'pending') {
// 改变状态为rejected
this.state = 'rejected';
// 保存失败原因
this.reason = reason;
// 遍历并执行失败回调数组中的函数
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 执行执行器函数,并传入resolve和reject函数
try {
executor(resolve, reject);
} catch (e) {
// 如果执行器函数抛出异常,直接调用reject函数
reject(e);
}
}
// 定义一个then方法,接收两个参数,分别是成功回调和失败回调
then(onFulfilled, onRejected) {
// 如果参数不是函数,就给一个默认函数,实现透传效果
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason
};
// 返回一个新的Promise对象,用于实现链式调用
let promise2 = new Promise((resolve, reject) => {
// 如果当前状态是fulfilled,就异步执行成功回调,并传入成功值
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
// 获取成功回调的返回值
let x = onFulfilled(this.value);
// 调用resolvePromise函数,处理返回值和新Promise对象的关系
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 如果成功回调抛出异常,直接调用reject函数
reject(e);
}
}, 0);
}
// 如果当前状态是rejected,就异步执行失败回调,并传入失败原因
if (this.state === 'rejected') {
setTimeout(() => {
try {
// 获取失败回调的返回值
let x = onRejected(this.reason);
// 调用resolvePromise函数,处理返回值和新Promise对象的关系
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 如果失败回调抛出异常,直接调用reject函数
reject(e);
}
}, 0);
}
// 如果当前状态是pending,就将成功回调和失败回调存入对应的数组中,等待状态改变时再执行
if (this.state === 'pending') {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
// 返回新的Promise对象
return promise2;
}
}
// 定义一个resolvePromise函数,用于处理成功回调或失败回调的返回值和新Promise对象的关系
function resolvePromise(promise2, x, resolve, reject) {
// 如果返回值和新Promise对象是同一个对象,就抛出类型错误
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 定义一个标志,用于防止多次调用resolve或reject函数
let called;
// 如果返回值是一个对象或函数,就认为它是一个thenable对象,有可能是一个Promise对象
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
// 获取then属性
let then = x.then;
// 如果then属性是一个函数,就认为它是一个Promise对象,就以它的状态作为新Promise对象的状态
if (typeof then === 'function') {
// 调用then方法,并传入两个函数作为参数
then.call(x, y => {
// 如果已经调用过resolve或reject函数,就直接返回
if (called) return;
// 否则将标志置为true
called = true;
// 递归调用resolvePromise函数,处理y值和新Promise对象的关系
resolvePromise(promise2, y, resolve, reject);
}, r => {
// 如果已经调用过resolve或reject函数,就直接返回
if (called) return;
// 否则将标志置为true
called = true;
// 直接调用reject函数,并传入r值
reject(r);
});
} else {
// 如果then属性不是一个函数,就直接调用resolve函数,并传入x值
resolve(x);
}
} catch (e) {
// 如果在获取或调用then属性时抛出异常,就直接调用reject函数,并传入e值
if (called) return;
called = true;
reject(e);
}
} else {
// 如果返回值不是一个对象或函数,就直接调用resolve函数,并传入x值
resolve(x);
}
}
// 使用上面的Promise实现 延迟x秒打印hello world
function delay(time,msg) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(msg);
}, time);
});
}
delay(1000,'hello world').then((msg) => {
console.log(msg);
});
} 很赞哦! (0)
相关文章
文章评论
-
-
-
0条评论