自定义Promise对象案例
2023-05-09 Js 897
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条评论