2.5.JavaScript异步流程控制-Promise其他方法

141 阅读3分钟
  • .catch:失败返回cb;
  • .finally:无论成功还是失败 都要执行cb;
  • Promise.reject
  • Promise.resolve
  • Promise.deferred:需要这个值进行测试;
  • Promise.all:全部成功才成功,有任一个失败,都会失败;
  • Promise.race:只执行最快执行的代码;

promise.js

function Promise(executor) {
  let self = this;
  // 保存Promise状态,默认pending;三个状态: pending, fulfilled 或 rejected.
  self.status = 'pending';
  // 保存成功的值
  self.value = undefined;
  // 保存失败的原因
  self.reason = undefined;
  // 异步方法存起来
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];

  // 只有Promise状态为pending才能进行转化
  function resolve(value) {
    if (self.status === 'pending') {
      self.value = value;
      self.status = 'fulfilled';
      // fulfilled执行异步的方法
      self.onResolvedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  function reject(reason) {
    if (self.status === 'pending') {
      self.reason = reason;
      self.status = 'rejected';
      // rejected执行异步的方法
      self.onRejectedCallbacks.forEach(function (fn) {
        fn();
      });
    }
  }
  try {
    executor(resolve, reject); // 跑出异常时,走下一个then的失败
  } catch (e) {
    reject(e); // 出错,reason就是原因
  }
}
// 核心方法:处理成功或失败执行的返回值,处理promise2的关系;
function resolvePromise(promise2, x, resolve, reject) {
  // 有可能x===promise2
  if (promise2 === x) {
    return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'));
  }
  // 如果是第三方的Promise
  let called; // 文档要求,一旦成功,不能调用失败
  if ((x !== null && typeof x === 'object') || typeof x === 'function') {
    // x可能是一个promise
    try {
      // x = {then:function(){}}
      let then = x.then; // 取then方法

      if (typeof then === 'function') {
        then.call(x, function (y) {
          if (!called) { called = true; } else { return; }
          resolvePromise(x, y, resolve, reject); // 递归检查promise
        }, function (r) {
          if (!called) { called = true; } else { return; }
          reject(r);
        });
      } else {
        resolve(x); // 普通值
      }
    } catch (error) {
      if (!called) { called = true; } else { return; }
      reject(error);
    }
  } else {
    // x是普通值,直接返回
    resolve(x);
  }
}
Promise.prototype.then = function (onFulFilled, onRejected) {
  // 判断onFulFilled和onRejected是函数
  onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : function (data) {
    return data;
  }
  onRejected = typeof onRejected === 'function' ? onRejected : function (err) {
    throw err;
  }
  let self = this;
  let promise2;
  promise2 = new Promise(function (resolve, reject) {
    // 成功后执行onFulFilled返回值
    if (self.status === 'fulfilled') {
      setTimeout(() => {
        try {
          // 限制需要做的事情就是把then中成功或者失败后执行的结果获取到
          // 判断是否为promise,是promise就让promise执行,取到这个promise的执行结果。
          let x = onFulFilled(self.value);
          // 判断promise2和x也是then函数返回的结果和promise2的关系,如果x是普通值,让promise2成功;如果是一个失败的promise,直接让promise2失败
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0)
    }
    // 失败后执行onRejected返回原因
    if (self.status === 'rejected') {
      setTimeout(() => {
        try {
          let x = onRejected(self.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (error) {
          reject(error);
        }
      }, 0)
    }
    // 当Promise的executor中有异步方法时
    if (self.status === 'pending') {
      self.onResolvedCallbacks.push(function () {
        setTimeout(() => {
          try {
            let x = onFulFilled(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0)
      })
      self.onRejectedCallbacks.push(function () {
        setTimeout(() => {
          try {
            let x = onRejected(self.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0)
      })
    }
  })
  // 调用then后返回一个Promise
  return promise2;
}

// 测试是否符合PromiseA+规范 cnpm i promises-aplus-tests -g
// 测试函数 $ promises-aplus-tests promise.js
Promise.deferred = Promise.defer = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd;
}

// 返回失败信息
Promise.prototype.catch = function (onRejected) {
  return this.then(null, onRejected);
}

// then简写,不论成功或失败都要执行回调函数,并把成功或失败的值向下传递;
Promise.prototype.finally = function (cb) {
  return this.then(function (data) {
    cb();
    return data;
  }, function (err) {
    cb();
    throw err;
  })
}

// 类调用的函数叫静态方法
// 静态方法:直接调用失败方法
Promise.reject = function (reason) {
  return new Promise(function (resolve, reject) {
    reject(reason);
  })
}

// 静态方法:直接调用成功方法
Promise.resolve = function (reason) {
  return new Promise(function (resolve, reject) {
    resolve(reason);
  })
}

// 静态方法:一组函数全都执行
Promise.all = function (promises) {
  return new Promise(function (resolve, reject) {
    let arr = [];
    let i = 0; // 记录一下成功的次数
    function processData(index, data) {
      arr[index] = data;
      if (++i === promises.length) { // 当数组的长度 和promise的个数相等时 说明所有的promise都执行完成了
        resolve(arr);
      }
    }
    for (let i = 0; i < promises.length; i++) {
      let promise = promises[i];
      if (typeof promise.then === 'function') {
        promise.then(function (data) {
          processData(i, data); // 把索引和数据 对应起来 方便使用
        }, reject)
      } else {
        processData(i, promise);
      }
    }
  })
}

// 静态方法:只执行最先执行的函数
Promise.race = function (promises) {
  return new Promise(function (resolve, reject) {
    for (let i = 0; i < promises.length; i++) {
      let promise = promises[i];
      if (typeof promise.then == 'function') {
        promise.then(resolve, reject)
      } else {
        resolve(promise);
      }
    }
  })
}
module.exports = Promise;