当前位置:   article > 正文

Promise手写 使用class方法_prefer-promise-reject-errors

prefer-promise-reject-errors

原来使用Promise

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

var p = new Promise((resolve, reject)=>{
    setTimeout(()=>{
        resolve(4)
    }, 0)
})
p.then((res)=>{
    //4 res
    console.log(res, 'res')
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
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');
  },
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
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);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我们这里可以看到如果写入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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

  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 */
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

现在跟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')
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 回到为我们这边
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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 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);
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122

使用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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号