Promise详解

1. Promise基本使用:

【1】Promise:两个实例参数,分别为PromiseState和PromiseResult,前者表示Promise状态,后者表示改变状态时传入的data数据.

  const p = new Promise((resolve, reject) => {
    resolve('Hello Promise Resolve');
  });

此时p为一个Promise对象,其PromiseState为fulfilled,PromiseResult为字符串'Hello Promise Resolve'

PromiseState三种状态: (1) pending 等待被改变状态 (2)fulfilled 成功(3)rejected 失败

【2】Promise.reject(data) :返回一个PromiseState为rejected的Promise对象,其PromiseResult根据data决定

【3】Promise.resolve(data) :返回一个Promise对象,其PromiseResult根据data决定

  其PromiseState分情况讨论:

  1. 若data为非Promise对象,则状态为fulfilled

  2. 若data为Promise对象,且其调用resolve,即data结果状态为fulfilled,那么此时返回的Promise对象状态也为fulfilled

  3. 若data为Promise对象,且其调用reject或throw抛出异常,即data结果状态为rejected,那么此时返回的Promise对象状态也为rejected

【4】Promise.prototype.then(onResolved,onRejected) :若Promise的状态为fulfilled,执行onResolved函数,否则执行onRejected函数,均返回一个Promise对象,且返回对象的状态和

Promise.resolve(data)方法判定方式一样. 【!!!即使是then方法的第二个函数也是如此,第二个函数不是无论如何都返回rejected】

【5】Promise.prototype.catch()

【6】Promise.all(Promises: Array) :数组中所有Promise对象的状态为成功才返回一个成功的Promise对象,否则返回一个失败的Promise对象.

成功时,PromiseResult包含所有数组中对象的data,而失败时只包含失败的Promise对象结果.

【7】Promise.race(Promises: Array) :数组中第一个改变状态的Promise对象的即返回的Promise对象.

 

2. Promise需要注意的问题:

【1】当指定多个成功或失败回调函数,即一个Promise对象执行多次then,它们均会执行.

【2】Promise对象改变状态和执行回调函数执行顺序问题:

  情况一:先改变状态

    (1)执行器中直接同步执行resolve、reject或抛出异常

  const p = new Promise((resolve, reject) => {
// 此处代码同步执行 resolve(); }); p.then(res
=> { console.log(res) }, err => { console.log(err) });

    (2)执行器中异步执行resolve、reject,但then方法同样异步执行,且执行时间比前者晚

  const p = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, 1000)
  });
  setTimeout(() => {
    p.then(res => {
      console.log(res)
    }, err => {
      console.log(err)
    });
  }, 2000);

【3】异常穿透

【4】链式调用

【5】中断链式调用 :在then中手动返回一个状态为pending的Promise对象即可

 

3. Promise手写源码:

【1】Promise对象

function Promise(executor) {
  this.PromiseState = 'pending';
  this.PromiseResult = undefined;
  const self = this;
  /* 当进行异步执行resolve和reject时,先执行回调,再改变状态,
  那么需要在执行回调时先把onResolved和onRejected保存,等改变状态时再执行 */
  this.callbacks = [];

  function resolve(data) {
    /* 判断确保Promise对象状态只能改变一次,即同时出现resolve和reject,只执行一次 */
    if (self.PromiseState !== 'pending') return;
    self.PromiseResult = data;
    self.PromiseState = 'fulfilled';

    // 多个then回调函数都可以执行
    setTimeout(() => {
      self.callbacks.forEach(item => {
        item.onResolved(data);
      })
    });

  }

  function reject(data) {
    if (self.PromiseState !== 'pending') return;
    self.PromiseResult = data;
    self.PromiseState = 'rejected';

    setTimeout(() => {
      self.callbacks.forEach(item => {
        item.onRejected(data);
      })
    });

  }

  try {
    executor(resolve, reject);
  } catch (e) {
    reject(e);
  }

}

 

【2】Promise 原型方法

(1)then

Promise.prototype.then = function (onResolved, onRejected) {
  const self = this;
  if (typeof onRejected !== 'function') {
    /* 用户只传入第一个函数, 解决异常穿透 */
    onRejected = err => {
      throw err;
    }
  }
  if (typeof onResolved !== 'function') {
    onResolved = result => {
      return result;
    }
  }
  return new Promise((resolve, reject) => {
    function callback(type) {
      try {
        let result = type(self.PromiseResult);
        if (result instanceof Promise) {
          /* 此种判断无法获取数据,因此使用then将v和r顺利传入 */
          // if (result.PromiseState === 'fulfilled') {
          //   resolve();
          // } else if (result.PromiseState === 'rejected') {
          //   reject();
          // }
          result.then(v => {
            resolve(v);
          }, r => {
            reject(r);
          })
        } else {
          resolve(result);
        }
      } catch (e) {
        reject(e);
      }
    }

    if (self.PromiseState === 'pending') {
      this.callbacks.push({
        onResolved: function () {
          callback(onResolved);
        },
        onRejected: function () {
          callback(onRejected);
        }
      })
    } else if (self.PromiseState === 'fulfilled') {
      setTimeout(() => {
        callback(onResolved);
      });

    } else if (self.PromiseState === 'rejected') {
      setTimeout(() => {
        callback(onRejected);
      });

    }
  });
};

 

(2)catch

Promise.prototype.catch = function (onRejected) {
  return this.then(undefined, onRejected);
};

 (3)Promise.resolve and Promise.reject

Promise.resolve = function (res) {
  return new Promise((resolve, reject) => {
    if (res instanceof Promise) {
      res.then(v => {
        resolve(v);
      }, r => {
        reject(r);
      })
    } else {
      resolve(res);
    }
  })
};

Promise.reject = function (err) {
  return new Promise((resolve, reject) => {
    reject(err);
  })
};

 (4)Promise.all

Promise.all = function (promises) {
  return new Promise((resolve, reject) => {
    let arr = [];
    let count = 0;
    for (let i=0;i<promises.length;i++) {
      promises[i].then(res => {
        arr[i] = res; /* 如果是异步,则采用arr.push会改变结果顺序,因此采用下标索引填充 */
        count++;
        if (count === promises.length) {
          resolve(arr);
        }
      }, err => {
        reject(err);
      })
    }
  })
};

(5)Promise.race

Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(res => {
        resolve(res);
      }, err => {
        reject(err);
      })
    }
  })
};

 

posted @ 2021-09-08 21:02  TwinkleG  Views(536)  Comments(0)    收藏  举报