# Promise

# 简介

异步解决方案 ===>(回调地狱)。

  • 状态不受外界影响
  • 状态变更不可逆

三种状态,pending,fulfilled,rejected。

const p1 = Promise.resolve("p1");
const p2 = Promise.resolve("p2");
const p3 = Promise.reject("p3");
const p4 = Promise.reject("p4");

# 缺点

  • 不可取消
  • 不知道当前是什么状态,刚开始或者快结束

# finally

无论状态的变更为何种状态,promise 都会去执行。执行顺序参照 finally 函数所在位置。

Promise.all([p1, p2])
  .finally((res) => {
    console.log("all resolve finally", res);
  })
  .then((res) => {
    console.log("all resolve", res);
    throw "all resolve";
  })
  .catch((err) => {
    console.log("all resolve catch", err);
  });

# all

当所有函数执行成功的时候,会执行传入的 resolve 函数。 当其中一个失败,就会将失败的结果,传入到 reject 函数中。

Promise.all([p1, p2, p3, p4])
  .then(
    (res) => {
      console.log("all resolve", res);
    },
    (err) => {
      console.log("all reject", err);
      throw "reject error";
    }
  )
  .catch((err) => {
    console.log("all catch", err);
  });

# race

只要有一个函数执行成功,就会执行传入的 resolve 函数。

全部失败的时候,执行传入的 reject 函数,函数的参数为第一个执行失败的结果。

Promise.race([p3, p4])
  .then(
    (res) => {
      console.log("race resolve", res);
    },
    (err) => {
      console.log("race reject", err);
      throw 1;
    }
  )
  .catch((err) => {
    console.log("race catch", err);
  });

# 其他

在一个 promise 里面返回一个,reject 的 promise,catch 也同样能够捕获。

p1.then((res) => {
  return p3;
}).catch((err) => {
  console.log("return reject", err);
});
const p5 = new Promise((resolve, reject) => {
  // 同步
  console.log(1);
  resolve();
  console.log(2);
});

p5.then((res) => {
  console.log(3);
});

console.log(4);

// 1
// 2
// 4
// 3
// promise构造函数只执行一次,一旦执行,后续调用then,都会直接拿到对应的值。
const p6 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("success");
  }, 1000);
});

const start = +new Date();

p6.then((res) => {
  console.log(+new Date() - start);
});
p6.then((res) => {
  console.log(+new Date() - start);
});
// 1005
// 1005 可能略有不同

# 实现

# 构造函数

// 1、构造函数
// 2、接收的一个executor为函数,executor函数有两个参数 resolve,reject,这两个函数定义在promise内部,供用户调用
// 3、状态status, pending, fulfilled, rejected 状态一旦改变,不能恢复

function MyPromise(executor) {
  var self = this;
  self.status = "pending"; // 当前执行状态
  self.data = undefined;
  // 操作成功,执行executor的resolve(第一个函数参数),并传入结果
  // 操作失败,执行executor的reject(第二个函数参数),并传入结果
  self.onResolvedCallback = []; // resolve函数集,Promise结束之前可能有多个回调添加到上面
  self.onRejectedCallback = []; // reject 函数集,Promise结束之前可能有多个回调添加到上面

  function resolve(value) {
    if (self.status === "pending") {
      self.status = "resolved";
      self.data = value;
      var resolveLength = self.onResolvedCallback.length;
      for (var i = 0; i < resolveLength; i++) {
        self.onResolvedCallback[i](value);
      }
    }
  }

  function reject(reason) {
    if (self.status === "pending") {
      self.status = "rejected";
      self.data = reason;
      var rejectLength = self.onRejectedCallback.length;
      for (var i = 0; i < rejectLength; i++) {
        self.onRejectedCallback[i](reason);
      }
    }
  }

  // resolve,reject 为两个函数,只会执行一个
  // executor 可能会报错,报错时,直接执行reject
  try {
    // resolve,reject 作为参数传递出去
    executor(resolve, reject);
  } catch (e) {
    reject(e);
  }
}

# then 方法

  • 定义在 Promise 的原型链上
  • 返回一个新的 Promise
  • 两个函数参数,onResolved、onRejected
MyPromise.prototype.then = function then(onResolved,onRejected){
    var self = this;
    var promise2;
    // onResolved,onRejected默认函数的返回值,用于值的穿透 => 内容直接向下传递。 function(v){ return v}
    onResolved = typeof onResolved === 'function'?onResolved:function(v){ return v};
    onRejected = typeof onRejected === 'function'?onRejected:function(r){ return r};
    if(self.status === 'resolved'){
        return promise2 = new MyPromise(function(resolve,reject){
            try{
                var x = onResolved(self.data);
                // 结果已经是promise的话,直接将x的执行结果作为返回
                // x 执行的结果传到当前的resolve(promise2),promise2的data变为x的执行结果
                if(x instanceof MyPromise){
                    x.then(resolve,reject)
                }
            }catch(e){
                reject(e)
            }
        })
    }
    if(self.status === 'rejected'){
        return promise2 = new MyPromise(function(resolve,reject){
             try{
                var x = onRejected(self.data);
                if(x instanceof MyPromise){
                    x.then(resolve,reject)
                }
            }catch(e){
                reject(e)
            }
        })
    }
    if(self.status === 'pending'){
        // 为pending时,直接加入到onResolvedCallback,onRejectedCallback中去,待执行结束后调用
        return promise2 = new MyPromise(function(resolve,reject){
           self.onResolvedCallback.push(function(value){
               var x = onResolved(value)
               if(x instanceof MyPromise){
                   x.then(resolve,reject)
               }
               resolve(x)
           })
           self.onRejectedCallback.push(function(value){
               var x = onRejected(value)
               if(x instanceof MyPromise){
                   x.then(resolve,reject)
               }
               reject(x)
           })
        })
    }
}


MyPromise.prototype.catch = function catch(onRejected){
    return this.then(null,onRejected)
}

MyPromise.prototype.resolve = function resolve(value){
    return new MyPromise(function(resolve,reject){
        resolve(value)
    })
}

MyPromise.prototype.reject = function reject(reason){
    return new MyPromise(function(resolve,reject){
        reject(reason)
    })
}

MyPromise.prototype.finally = function finally(fn){
    return this.then(function (value){
        fn()
    },function (reason){
        fn()
    })
}

var promise = new MyPromise((resolve,reject)=>{resolve(222)})

# 参考

Promise 必知必会 Promise 实现 Promise 面试题