Promise手写 使用class方法

原来使用Promise

用法不再多说,只是展示比较跟我下面写的使用方法

var p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve(4)
    }, 0)
})
p.then((res)=>{
    //4 res
    console.log(res, 'res')
})
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve(4);
    // eslint-disable-next-line prefer-promise-reject-errors
    reject(4);
  }, 0);
});
p.then(
  (res) => {
    console.log(res, 'res');
  },
  (err) => {
    // 4  err
    console.log(err, 'err');
  },
);
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    // resolve(4);
    // eslint-disable-next-line prefer-promise-reject-errors
    reject(4);
  }, 0);
});
p.then((res) => {
  console.log(res, 'res');
}).catch((e) => {
  // 4
  console.log(e);
});

我们这里可以看到如果写入then第二个参数后,可以处理reject的值,也可以通过catch来处理reject的值

手写Promise

  1. 创建一个class 对象 新增构建函数
class MyPromise {
  public constructor(fn: (resolve: (value: unknown) => void) => void) {
    // 成功
    const resolve = (value: unknown) => {
      console.log(value);
    };

    fn(resolve);
  }
}

const a = new MyPromise((resolve) => {
  resolve('123');
  /** 123 */
});

这样我们创建一个类,具有回调对象里面函数的方法。

  1. 新增状态,执行返回值,拒绝返回值
const PENDING = 'pending'; // 等待中
const FULFILLED = 'fulfilled'; // 执行
const REJECTED = 'rejected'; // 拒绝

class MyPromise {
  /** 执行状态 */
  state = PENDING;
  /** 执行返回 */
  value: any = null;
  /** 失败返回 */
  reason: any = null;
  public constructor(
    fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
  ) {
    const resolve = (value: unknown) => {
      // state改变,resolve调用就会失败
      if (this.state === 'pending') {
        // resolve调用后,state转化为成功态
        this.state = 'fulfilled';
        // 储存成功的值
        this.value = value;
        console.log(value);
      }
    };
    const reject = (reason: unknown) => {
      // state改变,reject调用就会失败
      if (this.state === 'pending') {
        // reject调用后,state转化为失败态
        this.state = 'rejected';
        // 储存失败的原因
        this.reason = reason;
      }
    };
    // 如果executor执行报错,直接执行reject
    try {
      fn(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
}

const a = new MyPromise((resolve) => {
  resolve('123');
  /** 123 */
});

现在跟Promise 使用方法还差一个then方法进行回调resolve方法
3.

  • 秘籍规定:Promise有一个叫做then的方法,里面有两个参数:onFulfilled,onRejected,成功有成功的值,失败有失败的原因
  • 当状态statefulfilled,则执行onFulfilled,传入this.value。当状态staterejected,则执行onRejected,传入this.value
  • onFulfilled,onRejected如果他们是函数,则必须分别在fulfilledrejected后被调用,valuereason依次作为他们的第一个参数。
  • 例子:以下是Promise,可以看得到resolve传进去就是4,这个值会传进then里面的res就是上面提到onFulfilled
var p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve(4)
    }, 0)
})
p.then((res)=>{
    //4 res
    console.log(res, 'res')
})
  • 回到为我们这边
const PENDING = 'pending'; // 等待中
const FULFILLED = 'fulfilled'; // 执行
const REJECTED = 'rejected'; // 拒绝

class MyPromise {
  /** 执行状态 */
  state = PENDING;
  /** 执行返回 */
  value: any = null;
  /** 失败返回 */
  reason: any = null;
  public constructor(
    fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
  ) {
    const resolve = (value: unknown) => {
      // state改变,resolve调用就会失败
      if (this.state === 'pending') {
        // resolve调用后,state转化为成功态
        this.state = 'fulfilled';
        // 储存成功的值
        this.value = value;
      }
    };
    const reject = (reason: unknown) => {
      // state改变,reject调用就会失败
      if (this.state === 'pending') {
        // reject调用后,state转化为失败态
        this.state = 'rejected';
        // 储存失败的原因
        this.reason = reason;
      }
    };
    // 如果executor执行报错,直接执行reject
    try {
      fn(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  // then 方法 有两个参数onFulfilled onRejected
  then(onFulfilled?: Function, onRejected?: Function) {
    // 状态为fulfilled,执行onFulfilled,传入成功的值
    if (onFulfilled && this.state === 'fulfilled') {
      onFulfilled(this.value);
    }
    // 状态为rejected,执行onRejected,传入失败的原因
    if (onRejected && this.state === 'rejected') {
      onRejected(this.reason);
    }
  }
}

const a = new MyPromise((resolve) => {
  resolve('123');
});

a.then((res: string) => {
  console.log(res);
  // 123
});
  1. 处理异步问题,现在基本可以实现简单的同步代码,但是当resolvesetTomeout内执行,thenstate还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们,优化一下代码
enum Status {
  PENDING = 'pending', // 等待中
  FULFILLED = 'fulfilled', // 执行
  REJECTED = 'rejected', // 拒绝
}

class MyPromise {
  /** 执行状态 */
  state: Status = Status.PENDING;
  /** 执行返回 */
  value: any = null;
  /** 失败返回 */
  reason: any = null;
  /** 成功存放的数组 */
  onResolvedCallbacks: Function[] = [];
  /** 失败存放法数组 */
  onRejectedCallbacks: Function[] = [];
  public constructor(
    fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
  ) {
    const resolve = (value: unknown) => {
      // state改变,resolve调用就会失败
      if (this.state === Status.PENDING) {
        // resolve调用后,state转化为成功态
        this.state = Status.FULFILLED;
        // 储存成功的值
        this.value = value;
        // 一旦resolve执行,调用成功数组的函数
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason: unknown) => {
      // state改变,reject调用就会失败
      if (this.state === Status.PENDING) {
        // reject调用后,state转化为失败态
        this.state = Status.REJECTED;
        // 储存失败的原因
        this.reason = reason;
        // 一旦reject执行,调用失败数组的函数
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    // 如果executor执行报错,直接执行reject
    try {
      fn(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  // then 方法 有两个参数onFulfilled onRejected
  then(onFulfilled?: Function, onRejected?: Function) {
    if (this.state === Status.FULFILLED && onFulfilled) {
      onFulfilled(this.value);
    }
    if (this.state === Status.REJECTED && onRejected) {
      onRejected(this.reason);
    }
    // 当状态state为pending时
    if (this.state === Status.PENDING) {
      if (onFulfilled && typeof onFulfilled === 'function') {
        // onFulfilled传入到成功数组
        this.onResolvedCallbacks.push(() => {
          onFulfilled(this.value);
        });
      }

      if (onRejected && typeof onRejected === 'function') {
        // onRejected传入到失败数组
        this.onRejectedCallbacks.push(() => {
          onRejected(this.value);
        });
      }
    }
  }
}

const a = new MyPromise((resolve) => {
  setTimeout(() => {
    console.log('444');
    resolve('123');
  }, 500);
  console.log('333');
});

a.then((res: string) => {
  console.log(res);
});
// 333 444 123 最终结果
  1. 如果上面的逻辑已经看懂后,接下来要看最关键的链式结构,意思是多个then使用, new Promise().then().then() ,这就是链式调用,用来解决回调地狱。
  • 例子
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(4);
    // eslint-disable-next-line prefer-promise-reject-errors
    // reject(4);
  }, 0);
});
p.then((res) => {
  // 4 res
  console.log(res, 'res');
  return res + 1;
}).then((res) => {
  // 5 res2
  console.log(res, 'res2');
});
  • 1、为了达成链式,我们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2: promise2 = new Promise((resolve, reject)=>{})
    •将这个promise2返回的值传递到下一个then中
    •如果返回一个普通的值,则将普通的值传递给下一个then中

  • 2、当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值

  • 秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise

  • 回归我们代码


enum Status {
  PENDING = 'pending', // 等待中
  FULFILLED = 'fulfilled', // 执行
  REJECTED = 'rejected', // 拒绝
}
class MyPromise {
  /** 执行状态 */
  state: Status = Status.PENDING;
  /** 执行返回 */
  value: any = null;
  /** 失败返回 */
  reason: any = null;
  /** 成功存放的数组 */
  onResolvedCallbacks: Function[] = [];
  /** 失败存放法数组 */
  onRejectedCallbacks: Function[] = [];
  /** 构造方法 是一个方法,里面有2个传参,第一个是 resolve 是方法传参是 成功回调传参, 第二个是reject方法 里面的参数是失败回调 */
  public constructor(
    fn: (resolve: (value: unknown) => void, reject: (reason: unknown) => void) => void,
  ) {
    const resolve = (value: unknown) => {
      // state改变,resolve调用就会失败
      if (this.state === Status.PENDING) {
        // resolve调用后,state转化为成功态
        this.state = Status.FULFILLED;
        // 储存成功的值
        this.value = value;
        // 一旦resolve执行,调用成功数组的函数
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason: unknown) => {
      // state改变,reject调用就会失败
      if (this.state === Status.PENDING) {
        // reject调用后,state转化为失败态
        this.state = Status.REJECTED;
        // 储存失败的原因
        this.reason = reason;
        // 一旦reject执行,调用失败数组的函数
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    // 如果executor执行报错,直接执行reject
    try {
      fn(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  // then 方法 有两个参数onFulfilled 是指 then(res)的res  res 就是 resolve()传进去的值 onRejected
  then(onFulfilled?: Function, onRejected?: Function) {
    // 声明返回的promise2
    const promise2 = new MyPromise((resolve, reject) => {
      if (this.state === Status.FULFILLED && onFulfilled) {
        const x = onFulfilled(this.value);
        this.resolvePromise(promise2, x, resolve, reject);
      }
      if (this.state === Status.REJECTED && onRejected) {
        const x = onRejected(this.reason);
        this.resolvePromise(promise2, x, resolve, reject);
      }
      // 当状态state为pending时
      if (this.state === Status.PENDING) {
        if (onFulfilled && typeof onFulfilled === 'function') {
          // onFulfilled传入到成功数组
          this.onResolvedCallbacks.push(() => {
            const x = onFulfilled(this.value);
            this.resolvePromise(promise2, x, resolve, reject);
          });
        }

        if (onRejected && typeof onRejected === 'function') {
          // onRejected传入到失败数组
          this.onRejectedCallbacks.push(() => {
            const x = onRejected(this.value);
            this.resolvePromise(promise2, x, resolve, reject);
          });
        }
      }
    });
    return promise2;
  }

  resolvePromise(
    promise2: MyPromise,
    x: any,
    resolve: (value: unknown) => void,
    reject: (value: unknown) => void,
  ) {
    if (promise2 === x) {
      return reject(new TypeError('Chaining cycle detected for promise #<promise>'));
    }
    // 判断如果x是否是一个对象,判断函数是否是对象的方法有:typeof instanceof constructor toString
    if ((typeof x === 'object' && x != null) || typeof x === 'function') {
      try {
        const then = x.then; // 取then可以报错,报错就走reject()
        if (typeof then === 'function') {
          // 用then.call()为了避免在使用一次x.then报错
          then.call(
            x,
            (y: any) => {
              console.log('y', y);
              resolve(y); // 采用promise的成功结果,并且向下传递
            },
            (r: any) => {
              reject(r); // 采用promise的失败结果,并且向下传递
            },
          );
        } else {
          resolve(x); // x不是一个函数,是一个对象
        }
      } catch (err) {
        reject(err);
      }
    } else {
      // x是一个普通值
      resolve(x);
    }
  }
}

使用demo

new MyPromise((resolve) => {
  setTimeout(() => {
    console.log('开始');
    resolve('a');
  }, 500);
})
  .then((res: string) => {
    console.log(res);
    console.log('结束');
    return 'b';
  })
  .then((res: string) => {
    console.log(res);
  });

new Promise((resolve) => {
  resolve('a');
})
  .then((res: any) => {
    console.log(res);
    return 'b';
  })
  .then((res: string) => {
    console.log(res);
  });

结果都是一样的可以使用
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Promise是一种异步编程的解决方案,可以避免回调地狱的问题。下面是使用class手写一个Promise的示例代码: ``` class MyPromise { constructor(executor) { this.status = 'pending'; // Promise的状态 this.value = undefined; // Promise的结果 this.reason = undefined; // Promise的错误信息 const resolve = (value) => { if (this.status === 'pending') { this.status = 'fulfilled'; this.value = value; } }; const reject = (reason) => { if (this.status === 'pending') { this.status = 'rejected'; this.reason = 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.status === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, ); } else if (this.status === 'rejected') { setTimeout(() => { try { const x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, ); } else { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, ); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, ); }); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } } function resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { reject(new TypeError('Chaining cycle detected for promise')); } let called = false; if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { const then = x.then; if (typeof then === 'function') { then.call(x, (y) => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, (r) => { if (called) return; called = true; reject(r); }); } else { resolve(x); } } catch (error) { if (called) return; called = true; reject(error); } } else { resolve(x); } } ``` 以上是一个简单的Promise实现,其中包含了Promise的基本功能,如状态管理、then方法、catch方法等。需要注意的是,Promise的实现并不是一件简单的事情,需要考虑到各种边界情况,才能保证其正确性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值