共计 8714 个字符,预计需要花费 22 分钟才能阅读完成。
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'}
}
正文完
发表至: javascript
2021-09-18