22.Promise(1)

88 阅读4分钟

在上一章中讲了事件循环和任务队列,里面有一个关键词是异步.我们讲到了异步就不得不提Promise(这部分内容比较多,可能会分为2章来讲).

Promise是什么

Promise是es6发布的新特性之一,对于现在来说也已经不新了,他已经发布了7年了,但是我们还是经常的使用他,时间证明了他的强大. Promise翻译过来就是承诺,在<<你不知道的JavaScript>>中是这样解释的,你去买汉堡,在柜台上,下订单付款,得到一个凭证,启动了一场交易.这个凭证代表了你未来的汉堡,你只需要耐心等待就行,期间你可以干其他事情,比如刷刷抖音. 你只需要时间到了,凭你手上的凭证去换取你的汉堡就行,但是也有可能出现另外一种情况,到了你的号的时候,服务员告诉你,你好意思,我们的汉堡买完了.这也是代表着promise的特性可能成功,也有可能失败.在代码中,事情并非这么简单。这是因为,用类比的方式来说就是,订单号可能永远不会被叫到。在这种情况下,我们就永远处于一种未决议状态。后面会讨论如何处理这种情况。

Promise能干什么

我们先来控制台输出一下Promise有什么功能.

image.png 我们可以看到Promise是一个构造函数,上面有我们熟悉的race,reject,resolve函数和原型链上的catch,finally,then函数 很多的开发者说Promise是为了解决毁掉地狱(有时间的话可以详细解释)而出现的.但是只是为了解决回调地狱对于已经2022年的现在来说似乎有点单薄了.现在我们在开发中涉及到异步的任务,我们都会想到Promise或者async await.这在一定程度上是升华了Promise的功能. 在异步操作我们往往会去获取到这个异步操作的结果,如果不用Promise我们往往会使用回调的形式,Promise可以使用.then.catch的方式去获取,虽然在链式编程中也是回调,但是规范了很多. 而且对于错误的情况也做了处理.

深入Promise

开始准备讲Promise的状态,resolve,reject,.then .catch...都已经快写完了,后来想了想不太直观.想换一种方式,有什么方式比手写一个自己的Promise更加直观了,所以

Promise的三种状态

 const PENDING = 'pending';
 const RESOVLED = 'resolved';
 const REJECTED = 'rejected';

定义一个Promise类

初始化数据

class MyPromise {
  constructor(executor) {
      let that = this;
          this.status = PENDING; //状态未变之前都是pending
          this.data = undefined; //未定义的数据
          this.callbacks = []; //每个元素的结构:onResolved(){},onRejected(){}
  }
}

定义Promise的resolve和reject 和回调错误捕获

          function resolve(value) {
            if (that.status !== PENDING) return;
            //调用resolve后,需要将状态改变成为resolved
            that.status = RESOVLED;
            //保存data数据
            that.data = value;
            //如果有未执行的callback,则立即异步执行onResolved,是包含两个回调的对象
            if (that.callbacks.length > 0) {
              setTimeout(() => {
                that.callbacks.forEach((element) => {
                  element.onResolved(value);
                });
              });
            }
          }
          function reject(reason) {
            if (that.status !== PENDING) return;
            //调用reject后,需要将状态改变成为rejected
            that.status = REJECTED;
            //保存data数据
            that.data = reason;
            //如果有未执行的callback,则立即异步执行onRejected,是包含两个回调的对象
            if (that.callbacks.length > 0) {
              setTimeout(() => {
                that.callbacks.forEach((element) => {
                  element.onResolved(reason);
                });
              });
            }
          }
          try {
            executor(resolve, reject);
          } catch (error) {
            reject(error);
          }

.then接收成功失败的回调返回新的MyPromise

  then(onResolved, onRejected) {
         const that = this;
         // 指定回调函数的默认值(必须是函数)
         onResolved =
           typeof onResolved === 'function' ? onResolved : (value) => value; //继续向下传递
         onRejected =
           typeof onRejected === 'function'
             ? onRejected
             : (reason) => {
                 throw reason;
               }; //抛出异常
         return new MyPromise((resolve, reject) => {
           if (this.status === PENDING) {
             //假设当前状态还是pending,将回调保存下来
             this.callbacks.push({
               onResolved(value) {
                 onResolved(that.data);
                 try {
                   const result = onResolved(that.data);
                   if (result instanceof MyPromise) {
                     result.then(
                       resolve,
                       reject
                     );
                   }
                 } catch (error) {
                   resolve(error);
                 }
               },
               onRejected(reason) {
                 onRejected(that.data);
                 try {
                   const result = onRejected(that.data);
                   if (result instanceof MyPromise) {
                     result.then(
                       resolve,
                       reject
                     );
                   }
                 } catch (error) {
                   reject(error);
                 }
               }
             });
           } else if (this.status === RESOVLED) {
             setTimeout(() => {
               //  如果回调是MyPromise,return的MyPromise结果就是这个MyPromise结果
               try {
                 const result = onResolved(that.data);
                 if (result instanceof MyPromise) {
                   result.then(
                     resolve,
                     reject
                   );
                 } else {
                   //返回的不是promise,返回promise为成功,value就是返回值
                   resolve(result);
                 }
               } catch (error) {
                 reject(error);
               }
             });
           } else {
             //如果前面的promise返回的是失败的回调
             setTimeout(() => {
               //  如果回调是promise,return的promise结果就是这个promise结果
               try {
                 const result = onRejected(that.data);
                 if (result instanceof MyPromise) {
                   result.then(
                     resolve,
                     reject
                   );
                 }
               } catch (error) {
                 try {
                   const result = onResolved(that.data);
                   if (result instanceof MyPromise) {
                     result.then(
                       resolve,
                       reject
                     );
                   }
                 } catch (error) {
                   reject(error);
                 }
               }
             });
           }
         });
       }

.catch接受失败回调

    catch(onRejected) {
          return this.then(undefined, onRejected);
        }

promise函数对象的resolve方法

static resolve(value) {
          return new MyPromise((resolve, reject) => {
            if (value instanceof MyPromise) {
              value.then(resolve, reject);
            } else {
              resolve(value);
            }
          });
        }

promise函数对象的reject方法

  static reject(reason) {
          return new MyPromise((resolve, reject) => {
            reject(reason);
          });
        }

今天先更新了Promise的resolve reject .then .catch 明天更新其他几个api 和一些实操,及异步的最终解决方案