第一步:编写constructor构造方法
javascript">const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';class MyPromise {#state = PENDING;#result = undefined;constructor(executor) {const resolve = (data) => {this.#changeState(FULFILLED, data)}const reject = (reason) => {this.#changeState(REJECTED, reason)}executor(resolve, reject)}#changeState(state, result) {if (this.#state === PENDING) return; // 状态一旦定下来,就不能再改变了this.#state = state;this.#result = result;}
}const p = new MyPromise((resolve, reject) => {resolve(1);reject(123); // 这里调用,不会起到任何作用
})console.log(p);
注意:状态一旦确定,就不能再改变的promise的状态
第二步:考虑异常情况
javascript">//用try catch包裹executor方法处理
//...try {executor(resolve, reject)} catch (err) {reject(err)}
//...const p = new MyPromise((resolve, reject) => {throw 123;
})
但是这种处理方式,对于异步的报错,没有办法
javascript">const p = new MyPromise((resolve, reject) => {setTimeout(() => {throw 123;}, 1000);
})
这个异步抛异常的问题是没法解决的,官方的实现也存在这个问题,异步抛异常是无法改变promise状态(没有执行changeState方法)
第三步:实现then方法(比较复杂)
一般会这么调用then方法
javascript">const p = new MyPromise((resolve, reject) => {setTimeout(() => {resolve("ok");}, 1000);
})//这个方法会优先于上面的setTimeout方法执行,所以会被记录,然后在setTimeout后执行
p.then(res => {console.log(res + 1);},err => {console.log(err);}
)p.then(res => {console.log(res + 2);},err => {console.log(err);}
)
图解:在调用then方法的时候,记录当前的参数 ,等setTimeout时间一到,就去执行#run方法
此时实现的MyPromise的代码如下
javascript">const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';class MyPromise {#state = PENDING;#result = undefined;#handlers = []; //记录多少个then的回调方法constructor(executor) {const resolve = (data) => {this.#changeState(FULFILLED, data)}const reject = (reason) => {this.#changeState(REJECTED, reason)}try {executor(resolve, reject)} catch (err) {reject(err)}}//状态改变时,调用这个方法#changeState(state, result) {if (this.#state !== PENDING) return; // 状态一旦定下来,就不能再改变了this.#state = state;this.#result = result;this.#run();}//执行handlers里面的方法,handlers的方法是调用then时,所记录的方法#run() {if (this.#state === PENDING) return;while (this.#handlers.length) {const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift();if (this.#state === FULFILLED) {if (typeof onFulfilled === 'function') {onFulfilled(this.#result);}} else {if (typeof onRejected === 'function') {onRejected(this.#result);}}}}then(onFulfilled, onRejected) {return new MyPromise((resolve, reject) => {//记录到#handlers这个变量中,等setTimeout时间一到,就去执行onFulfilled或者onRejected方法//resolve和reject是返回的一个新的promise的参数,这个新的promise用户链式调用(下面会写)this.#handlers.push({onFulfilled,onRejected,resolve,reject})this.#run();})}
}const p = new MyPromise((resolve, reject) => {setTimeout(() => {resolve("ok");}, 1000);
})//这个方法会优先于上面的setTimeout方法执行,所以会被记录到setTimeout后执行
p.then(res => {console.log(res + 1);},err => {console.log(err);}
)p.then(res => {console.log(res + 2);},err => {console.log(err);}
)
第四步:then的链式调用(比较复杂)
返回的是一个新的promise对象(以前面试有被问道,我回答错了)
javascript">//1.编写constructor构造方法,需要考虑状态一旦确定,就不能再改变的因素
const p = new MyPromise((resolve, reject) => {setTimeout(() => {resolve(1);}, 1000);
})//这个方法会优先于上面的setTimeout方法执行,所以会被记录到setTimeout后执行
p.then(res => {console.log(res); //1return res + 1},err => {console.log(err);}
).then(res => {console.log(res); //2
}, err => {console.log(err);
})
javascript">// 手写Promiseconst PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';class MyPromise {#state = PENDING;#result = undefined;#handlers = [];constructor(executor) {const resolve = (data) => {this.#changeState(FULFILLED, data)}const reject = (reason) => {this.#changeState(REJECTED, reason)}try {executor(resolve, reject)} catch (err) {reject(err)}}#changeState(state, result) {if (this.#state !== PENDING) return; // 状态一旦定下来,就不能再改变了this.#state = state;this.#result = result;this.#run();}//判断是不是Promise类型#isPromiseLike(value) {if (value !== null && (typeof value === 'object' || typeof value.then === 'function')) {return typeof value.then === 'function';}return false;}//微队列#runMicroTask(func) {//node环境中if (typeof process === 'object' && typeof process.nextTick === 'function') {process.nextTick(func);}//浏览器环境中else if (typeof MutationObserver === 'function') {const observer = new MutationObserver(func); //观察器const p = document.createTextNode('1');observer.observe(p, { characterData: true }); //当p节点发生改变的时候,执行funcp.data = '2';} else {setTimeout(func, 0);}}#runOne(callback, resolve, reject) {this.#runMicroTask(() => {//如果传来的不是function类型if (typeof callback !== 'function') {const settled = this.#state === FULFILLED ? resolve : reject;settled(this.#result); //将把当前的promise状态,传给下一个promisereturn;}//如果传来的是function类型try {const data = callback(this.#result);if (this.#isPromiseLike(data)) {data.then(resolve, reject);} else {reject(data);}} catch (err) {reject(err)}})}#run() {if (this.#state === PENDING) return;while (this.#handlers.length) {const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift();if (this.#state === FULFILLED) {this.#runOne(onFulfilled, resolve, reject)} else {this.#runOne(onRejected, resolve, reject)}}}then(onFulfilled, onRejected) {return new MyPromise((resolve, reject) => {this.#handlers.push({onFulfilled,onRejected,resolve,reject})this.#run();})}
}//1.编写constructor构造方法,需要考虑状态一旦确定,就不能再改变的因素
const p = new MyPromise((resolve, reject) => {setTimeout(() => {resolve(1);}, 1000);
})//这个方法会优先于上面的setTimeout方法执行,所以会被记录到setTimeout的定时时间到后执行
p.then(null, //如果不是一个函数,就延续上一个promise的状态err => {console.log(err);}).then(data => {console.log(data); //1},err => {console.log(err);})