Promsie js实现
step 1
初始化promise对象:
const PENDING = 'pending';const FULFILLED = 'fulfilled';const REJECTED = 'rejected';class MPromise { /** * * @param {Function} fn (resolve, reject) */ constructor(fn){ // 初始状态为pending this.status = PENDING; this.value = null; this.reason = null; } resolve(value){ } reject(resaon){ }}
step 2
实现resolve 和 reject办法
/** * * @param {Function} fn (resolve, reject) */ constructor(fn){ // 初始状态为pending this.status = PENDING; this.value = null; this.reason = null; try{ fn(this.resolve.bind(this), this.reject.bind(this)); // 为什么须要 bind(this) ? // 传入的fn可能是一个一般的函数,并不是箭头函数,有他本人的执行环境 }catch(e){ this.reject(e); } } resolve(value){ // 判断状态 只有PENDING才能够批改状态 if(this.status === PENDING){ this.value = value; this.status = FULFILLED; } } reject(resaon){ // 判断状态 只有PENDING才能够批改状态 if(this.status === PENDING){ this.resaon = resaon; this.status = REJECTED; } }
step 3
then办法的实现
then(onFulfilled, onRejected){ // 增加兜底函数 const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value; }; const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason; }; // .then的返回值整体是一个promise const promise = new MPromise((resolve, reject) => { switch(this.status){ case FULFILLED: { realOnFulfilled(); break; } case REJECTED: { realOnRejected(); break; } } }) return promise; } // 工具函数 判断是否function isFunction(value){ return typeof value === 'function' }
须要思考到promise外部如果是一个异步resolve或者reject办法的状况,此时状态仍是pending.
// 增加两个数组,存储一部resolve reject办法 FULFILLED_CALLBACK_LIST = []; REJECTED_CALLBACK_LIST = []; then(onFulfilled, onRejected){ //... // .then的返回值整体是一个promise const promise = new MPromise((resolve, reject) => { switch(this.status){ // ... case PENDING: { this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled); this.REJECTED_CALLBACK_LIST.push(realOnRejected); break; } } }) return promise; }
那么如何去保护FULFILLED_CALLBACK_LIST REJECTED_CALLBACK_LIST这两个数组,到底什么时候去掉用呢?
能够应用es6的get和set去保护
// 增加一个新的变量来保护状态 _status = PENDING; get status(){ return this._status; } set status(newStatus){ this._status = newStatus; switch(newStatus){ case FULFILLED: { this.FULFILLED_CALLBACK_LIST.forEach(callback => { callback(this.value); }) break; } case REJECTED: { this.REJECTED_CALLBACK_LIST.forEach(callback => { callback(this.resaon); }) break; } } }
依据promiseA+标准 onFulfilled 和 onRejected执行的异样,promsie须要被rejected,并且执行后果需调用resolvePromise办法,所以须要对realOnFulfilled 和 realOnRejected函数增加try catch捕捉异样,调用resolvePromise
then(onFulfilled, onRejected){ // ... // .then的返回值整体是一个promise const promise2 = new MPromise((resolve, reject) => { // onFulfilled 和 onRejected执行的异样,promsie须要被rejected const fulfilledMircotask = () => { try{ const x = realOnFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } } const rejectedMircotask = () => { try{ const x = realOnRejected(this.resaon); this.resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } } switch(this.status){ case FULFILLED: { fulfilledMircotask(); break; } case REJECTED: { rejectedMircotask(); break; } case PENDING: { this.FULFILLED_CALLBACK_LIST.push(fulfilledMircotask); this.REJECTED_CALLBACK_LIST.push(fulfilledMircotask); break; } } }) return promise2; } resolvePromise(promise2, x, resolve, reject){ }
promise中onFulfilled, onRejected为微工作,应用queueMicroTask进行包裹
const promise2 = new MPromise((resolve, reject) => { const fulfilledMircotask = () => { queueMicrotask(() => { try{ const x = realOnFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }) } const rejectedMircotask = () => { queueMicrotask(() => { try{ const x = realOnRejected(this.resaon); this.resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }) } // ... })
step 4
实现resolvePromise办法
resolvePromise(promise2, x, resolve, reject){ // 如果x promise相等 if(promise2 === x){ return reject(new TypeError('the promise and the return value are the same')) } // 如果x是一个promsie 那么让新的promise接口x的状态 // 那继续执行x,如果执行的时候又返回了一个y,那么持续解析y if(x instanceof MPromise){ // 这里也是执行了promise 须要queueMicrotask包裹下 queueMicrotask(() => { x.then(y => { this.resolvePromise(promise2, y, resolve, reject); }, reject); }) }else if(typeof x === 'object' && this.isFunction(x)){ if(x === null){ return reject(x); } let then = null; try{ // 去x.then的值赋值给then then = x.then; }catch(e){ return reject(e); } // 如果获取的then是一个函数 if(this.isFunction(then)){ // flag 确保只被执行一次 let called = false; try{ then.call( x, (y) => { if(called){ return; } called = true; this.resolvePromise(promise2, y, resolve, reject); }, (r) => { if(called){ return; } called = true; reject(r); } ) }catch(err){ if(called){ return; } reject(err); } }else{ resolve(x); } }else{ resolve(x) } }
step 5
catch办法实现就很简略了
catch(onRejected){ this.then(null, onRejected); }
step 6
除了这些 promsie还有一些静态方法,eg resolve reject。 什么是静态方法?
static resolve(value){ if(value instanceof MPromise){ return value; } return new Promise((resolve, reject) => { resolve(value); }) } static reject(reason){ return new Promise((resolve, reject) => { reject(reason); }) } // race状态是依靠外部执行最快的那个状态 static race(promiseList){ if(!Array.isArray(promiseList)){ return } return new Promise((resolve, reject) => { if(promiseList.length === 0){ resolve(); }else{ promiseList.forEach(promise => { MPromise.resolve(promise).then( val => resolve(val), reason => reject(reason) ) }) } }) } static all(promiseList){ if(!Array.isArray(promiseList)){ return } return new Promise((resolve, reject) => { if(promiseList.length === 0){ resolve([]); }else{ let count = []; let res = []; promiseList.forEach((promise, index) => { MPromise.resolve(promise).then( val => { res[index] = val; count++; if(count === promiseList.length){ // 可否用 index === promiseList.length 来做判断 为什么? resolve(res) } }, reason => reject(reason) ) }) } }) } // ...
残缺代码
const PENDING = 'pending';const FULFILLED = 'fulfilled';const REJECTED = 'rejected';class MPromise { // 增加两个数组,存储一部resolve reject办法 FULFILLED_CALLBACK_LIST = []; REJECTED_CALLBACK_LIST = []; _status = PENDING; /** * @param {Function} fn (resolve, reject) */ constructor(fn){ // 初始状态为pending this.status = PENDING; this.value = null; this.reason = null; try{ fn(this.resolve.bind(this), this.reject.bind(this)); // 为什么须要 bind(this) ? // 传入的fn可能是一个一般的函数,并不是箭头函数,有他本人的执行环境 }catch(e){ this.reject(e); } } resolve(value){ // 判断状态 只有PENDING才能够批改状态 if(this.status === PENDING){ this.value = value; this.status = FULFILLED; } } reject(resaon){ // 判断状态 只有PENDING才能够批改状态 if(this.status === PENDING){ this.resaon = resaon; this.status = REJECTED; } } get status(){ return this._status; } set status(newStatus){ this._status = newStatus; switch(newStatus){ case FULFILLED: { this.FULFILLED_CALLBACK_LIST.forEach(callback => { callback(this.value); }) break; } case REJECTED: { this.REJECTED_CALLBACK_LIST.forEach(callback => { callback(this.resaon); }) break; } } } then(onFulfilled, onRejected){ // 增加兜底函数 const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value; }; const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason; }; // .then的返回值整体是一个promise const promise2 = new MPromise((resolve, reject) => { // onFulfilled 和 onRejected执行的异样,promsie须要被rejected const fulfilledMircotask = () => { queueMicrotask(() => { try{ const x = realOnFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }) } const rejectedMircotask = () => { queueMicrotask(() => { try{ const x = realOnRejected(this.resaon); this.resolvePromise(promise2, x, resolve, reject); }catch(e){ reject(e); } }) } switch(this.status){ case FULFILLED: { fulfilledMircotask(); break; } case REJECTED: { rejectedMircotask(); break; } case PENDING: { this.FULFILLED_CALLBACK_LIST.push(fulfilledMircotask); this.REJECTED_CALLBACK_LIST.push(fulfilledMircotask); break; } } }) return promise2; } resolvePromise(promise2, x, resolve, reject){ // 如果x promise相等 if(promise2 === x){ return reject(new TypeError('the promise and the return value are the same')) } // 如果x是一个promsie 那么让新的promise接口x的状态 // 那继续执行x,如果执行的时候又返回了一个y,那么持续解析y if(x instanceof MPromise){ // 这里也是执行了promise 须要queueMicrotask包裹下 queueMicrotask(() => { x.then(y => { this.resolvePromise(promise2, y, resolve, reject); }, reject); }) }else if(typeof x === 'object' && this.isFunction(x)){ if(x === null){ return reject(x); } let then = null; try{ // 去x.then的值赋值给then then = x.then; }catch(e){ return reject(e); } // 如果获取的then是一个函数 if(this.isFunction(then)){ // flag 确保只被执行一次 let called = false; try{ then.call( x, (y) => { if(called){ return; } called = true; this.resolvePromise(promise2, y, resolve, reject); }, (r) => { if(called){ return; } called = true; reject(r); } ) }catch(err){ if(called){ return; } reject(err); } }else{ resolve(x); } }else{ resolve(x) } } catch(onRejected){ this.then(null, onRejected); } static resolve(value){ if(value instanceof MPromise){ return value; } return new Promise((resolve, reject) => { resolve(value); }) } static reject(reason){ return new Promise((resolve, reject) => { reject(reason); }) } // race状态是依靠外部执行最快的那个状态 static race(promiseList){ if(!Array.isArray(promiseList)){ return } return new Promise((resolve, reject) => { if(promiseList.length === 0){ resolve(); }else{ promiseList.forEach(promise => { MPromise.resolve(promise).then( val => resolve(val), reason => reject(reason) ) }) } }) } static all(promiseList){ if(!Array.isArray(promiseList)){ return } return new Promise((resolve, reject) => { if(promiseList.length === 0){ resolve([]); }else{ let count = []; let res = []; promiseList.forEach((promise, index) => { MPromise.resolve(promise).then( val => { res[index] = val; count++; if(count === promiseList.length){ // 可否用 index === promiseList.length 来做判断 为什么? resolve(res) } }, reason => reject(reason) ) }) } }) } // 工具函数 判断是否function isFunction(value){ return typeof value === 'function' }}