手写实现一个Promise

手写实现一个Promise

开发中 promise 的使用频率还是很高的,面试中几乎也是必考的。在这边记录一下如何自己手写实现一个 promise。原生的ES6自带了 promise ,不用考虑兼容性。

实现 Promise

  • Promise 是一个类,在使用的时候,需要 new 这个类
  • 在 new Promise 的时候,需要传入一个 executor 执行器,默认会立即被调用,且参数有两个(resolve ,reject)
  • Promise 有3种状态,pendding 默认等待状态,onFulfilled 成功态,onRejected 失败态。(promise默认就是 pendding ,当用户调用 resolve 时会变成成功态 ,调用 reject 的时候会变成失败态。成功可以传入成功的原因,失败可以传入失败的原因 )
  • new Promise 会返回一个 promise 实例,这个实例上有一个 then 方法,then 方法中有两个参数,一个是成功的回调一个是失败的回调。
  • 走向失败有两种情况 ,1.reject() 2.用户主动抛出异常
  • 一个 promise 中可以 then 多次(发布订阅模式)
  • promise 的状态是不能从成功变成失败,也不能从失败变成成功,只有 pendding 的时候才能更改状态
function resolvePromise(x, promise2, resolve, reject) {
  // x 决定promise2 的状态 走成功还是失败
  if (promise2 === x) {
    return reject(new TypeError("循环引用"));
  }
  // 判断x 是不是一个promise 先保证x 得是一个对象或者函数,如果不是对象或者函数那么x 一定不是promise
  if ((typeof x === "object" && x !== null) || typeof x === "function") {
    let called;
    // 需要看 这个x 上有没有then方法 有then方法才说明他是一个promise
    try {
      let then = x.then; // x可能是别人写的promise 那么取then有风险,
      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            // x.then((y)=>{},r=>{}) 取then就会有风险
            if (called) return;
            called = true;
            resolvePromise(y, promise2, resolve, reject); // 递归解析直到我们的y的值是一个普通值
          },
          (r) => {
            if (called) return;
            called = true;
            reject(r);
          }
        );
      } else {
        //  没有then方法的都执行这里
        resolve(x); // 只是一个对象而已 就是一个普通值
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    // x 就是一个普通的值,直接把x 传递给promise2的成功即可
    resolve(x);
  }
}
class Promise{
	constructor(executor) {
	    this.value = undefined; //成功的原因
	    this.reason = undefined; //失败的原因
	    this.status = PENDING; //状态
	    this.onResvoledCallbacks = []; //存放成功的回调
	    this.onRejectedCallbacks = []; //存放失败的回调
	    //成功
	    const resolve = (value) => {
	      // 如何判断是不是一个promise 主要看有没有then方法
	      if (value instanceof Promise) {
	        return value.then(resolve, reject);
	      }
	      if (this.status === "PENDDING") {
	        this.status = "FULFILLED";
	        this.value = value;
	        this.onResvoledCallbacks.forEach((fn) => fn());
	      }
	    };
	    //失败
	    const reject = (reason) => {
	      if (this.status === "PENDDING") {
	        this.status = "REJECTED";
	        this.reason = reason;
	        this.onRejectedCallbacks.forEach((fn) => fn());
	      }
	    };
	    try {
	      executor(resolve, reject);
	    } catch (e) {
	      reject(e);
	    }
	}
	
	then(onFulfilled, onRejected) {
	    // 有可能这个 onFulfilled, onRejected 是可选的
	    onFulfilled = typeof onFulfilled === "function" ? onFulfilled: 
	    	  function (data) { return data;};
	    onRejected = typeof onRejected === "function" ? onRejected : 
	    	  (err) => { throw err;};
	    let promise2 = new Promise((resolve, reject) => {
	      if (this.status === "FULFILLED") {
	        setTimeout(() => {
	          try {
	            let x = onFulfilled(this.value);
	            resolvePromise(x, promise2, resolve, reject);
	          } catch (e) {
	            reject(e);
	          }
	        }, 0);
	      }
	      if (this.status === "REJECTED") {
	        setTimeout(() => {
	          try {
	            let x = onRejected(this.reason);
	            resolvePromise(x, promise2, resolve, reject);
	          } catch (e) {
	            reject(e);
	          }
	        }, 0);
	      }
	      if (this.status === "PENDDING") {
	        this.onResvoledCallbacks.push(() => {
	          setTimeout(() => {
	            try {
	              let x = onFulfilled(this.value);
	              resolvePromise(x, promise2, resolve, reject);
	            } catch (e) {
	              reject(e);
	            }
	          }, 0);
	        });
	        this.onRejectedCallbacks.push(() => {
	          setTimeout(() => {
	            try {
	              let x = onRejected(this.reason);
	              resolvePromise(x, promise2, resolve, reject);
	            } catch (e) {
	              reject(e);
	            }
	          }, 0);
	        });
	      }
	    });
	    return promise2;
  }
}

Promise Api

1、Promise.all
  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
 static all(values) {
    return new Promise((resolve, reject) => {
      let times = 0;
      function processMap(key, value) {
        arr[key] = value;
        if (++times === values.length) {
          resolve(arr);
        }
      }
      const arr = [];
      for (let i = 0; i < values.length; i++) {
        let val = values[i]; // 可能是promise 也有可能是普通值
        let then = val && val.then;
        if (typeof then === "function") {
          then.call(
            val,
            (data) => {
              // 获取成功的结果
              processMap(i, data);
            },
            reject
          );
        } else {
          processMap(i, val);
        }
      }
    });
  }
2、Promise.race
  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
  • 面试时常考察超时如何处理,以及和promise.all的区别。
3、Promise.finally
  • 无论成功还是失败都执行,只要调用了就会执行
finally(cb) {
    return this.then(
      (y) => {
        return Promise.resolve(cb()).then(() => y);
      },
      (r) => {
        return Promise.resolve(cb()).then(() => {
          throw r;
        });
      }
    );
  }
4、Promise.resolve

返回一个Promise实例,这个实例处于resolve状态。根据传入的参数不同有不同的功能:

  • 值(对象、数组、字符串等):作为resolve传递出去的值
  • Promise实例:原封不动返回
5、Promise.reject

返回一个Promise实例,这个实例处于reject状态。参数一般就是抛出的错误信息。

好的,以下是一个简单的手写Promise实现: ```javascript class MyPromise { constructor(executor) { this.state = 'pending'; this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach((callback) => callback(this.value)); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach((callback) => callback(this.reason)); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value; onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason; }; const promise2 = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } else if (this.state === 'rejected') { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } else { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { reject(new TypeError('Chaining cycle detected')); } let called = false; if (x instanceof MyPromise) { x.then((value) => { this.resolvePromise(promise2, value, resolve, reject); }, (reason) => { if (!called) { called = true; reject(reason); } }); } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { const then = x.then; if (typeof then === 'function') { then.call(x, (value) => { if (!called) { called = true; this.resolvePromise(promise2, value, resolve, reject); } }, (reason) => { if (!called) { called = true; reject(reason); } }); } else { resolve(x); } } catch (error) { if (!called) { called = true; reject(error); } } } else { resolve(x); } } static resolve(value) { return new MyPromise((resolve) => { resolve(value); }); } static reject(reason) { return new MyPromise((resolve, reject) => { reject(reason); }); } static all(promises) { const results = []; return new MyPromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { const promise = promises[i]; if (!(promise instanceof MyPromise)) { promise = MyPromise.resolve(promise); } promise.then((value) => { results[i] = value; if (results.length === promises.length) { resolve(results); } }, (reason) => { reject(reason); }); } }); } static race(promises) { return new MyPromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { const promise = promises[i]; if (!(promise instanceof MyPromise)) { promise = MyPromise.resolve(promise); } promise.then((value) => { resolve(value); }, (reason) => { reject(reason); }); } }); } } ``` 这个实现包含了Promise的基本功能,包括resolve、reject、then、catch、resolvePromise等方法,并且还实现Promise.all和Promise.race方法。但是这个实现并不完整,还有很多细节需要考虑和完善。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值