你不知道的Promise细节

Posted 还是不会呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你不知道的Promise细节相关的知识,希望对你有一定的参考价值。

异步请求处理方案

在ES6之前,对于网络请求的结果是通过回调函数实现的。

回调函数

Promise重构

Promise的基本使用

// 创建一个Promise实例
// 传入一个回调函数,该函数在Promise内部直接执行
// 1、resolve是一个函数 2、 reject也是一个函数。
const promise = new Promise((resolve, reject) => {
  console.log("我会直接执行打印~");
  //   resolve("fzb");
  reject(21);
});

// promise内的resolve函数执行,会执行promise上的then传入的回调函数,并且将参数传过来
// promise内的reject函数执行,会执行promise上的catch传入的回调函数,错误信息将会传过来

// 1、结果处理和错误处理回调函数放在一个then里边执行
// promise.then(
//   (res) => {
//     console.log(res); // "fzb"
//   },
//   (err) => {
//     console.log(err);
//   }
// );
// 2、结果处理和错误处理函数链式调用
// promise.then((res) => console.log(res)).catch((err) => console.log(err));

// 3、 结果处理和错误处理分开
// 这种情况在node或者浏览器上会存在错误,因为在定义Promise时执行的reject而在处理时是先对then这种情况先处理
// 也就是说下面两行代码,promise在错误需要处理时却先处理的是then的方法,是不匹配的,只有这种情况会报错
promise.then((res) => console.log(res));
promise.catch((err) => console.log(err));

Promsie的三种状态

const promsie = new Promise((resolve, reject) => {
  // 在执行resolve()函数和reject()之前,promise所处状态: pending(进行中)
  resolve(); // promsie所处状态: pending(进行中) --->>>  fulfilled(成功)
  reject(); // promise所处状态:pending(进行中) --->>>  rejected(失败)
  console.log("我还是会执行的~~~");
});
// 注意:promise状态进行改变完,就已经确定,如上方代码 执行完之后promise的状态为:fulfilled,
//      这并不意味着resolve()或reject()执行之后,后面的代码就不执行了

Promise的resolve参数

// 1、resolve()方法内传入普通的值或者对象
const promsie1 = new Promise((resolve, reject) => {
  // const info = "i am fzb";
  const info = { name: "fzb", age: 21 };
  resolve(info);
});
// then传入的回调函数内的参数取到的内容是:传入普通的值或者对象
promsie1.then((res) => console.log(res)); // { name: 'fzb', age: 21 }

// 2、resolve()方法内传入一个Promise对象
const promise2 = new Promise((resolve, reject) => {
  resolve(
    new Promise((resolve, reject) => {
      // const info = "i am fzb";
      const info = { name: "fzb", age: 21 };
      resolve(info);
    })
  );
});
// then传入的回调函数内的参数取到的内容是:传入promise对象内的resolve()上传入的内容决定的
promise2.then((res) => console.log(res)); // { name: 'fzb', age: 21 }

// 3、resolve()方法内传入一个对象,并且对象行还有 then方法[即实现的thenable接口]。
const promise3 = new Promise((resolve, reject) => {
  const obj = {
    then: function (resolve, reject) {
      resolve("我是obj对象内then方法内传入的");
    },
  };
  resolve(obj);
});
// then传入的回调函数内的参数取到的内容是: 传入对象内的then上的resolve参数执行传入的内容决定的
promise3.then((res) => console.log(res)); // 我是obj对象内then方法内传入的

Promse的reject参数

reject参数不像resolve参数一样,resolve参数传入的内容类型不同会有不一样的结构,但是reject参数传入的内容不会影响catch的回调函数内参数的值。

const promise = new Promise((resolve, reject) => {
  // 1、传入一个普通对象或者值
  // reject("error message");
  // 2、传入一个对象,并且还有then方法
  //   reject({
  //     then(resolve, reject) {
  //       reject("aaa");
  //     },
  //   });
  // 3、传入一个Promise
  //   reject(
  //     new Promise((resolve, reject) => {
  //       reject("aaa");
  //     })
  //   );
});
promise.catch((err) => {
  console.log(err);
});

Promise对象方法

**console.log(Object.getOwnPropertyDescriptors(Promise.prototype));**获取Promise上的方法存在三个:thencatchfinally

then方法

1、同一个Promise可以被多个then方法调用

const promise = new Promise((resolve, reject) => {
  resolve("fzb");
});
promise.then((res) => console.log("res1:", res)); // res1: fzb
promise.then((res) => console.log("res2:", res)); // res2: fzb
promise.then((res) => console.log("res3:", res)); // res3: fzb

2、then方法的传入的回调函数可以有返回值,返回值也是一个Promise对象

但是:此时后面的then处理的Promise不是同一个Promsie对象了

// 1> 若返回值是一个普通的值或者对象
new Promise((resolve, reject) => {
  // const info = "i am fzb";
  const info = { name: "fzb", age: 21 };
  resolve(info);
})
  .then((res) => {
    console.log("res:", res); // res: { name: 'fzb', age: 21 }
    return res;
  })
  .then((res) => {
    console.log("res:", res); // res: { name: 'fzb', age: 21 }
  });

// 2> 若返回值是一个Promsie对象
new Promise((resolve, reject) => {
  resolve(
    new Promise((resolve, reject) => {
      resolve("hahahaha");
    })
  );
})
  .then((res) => {
    console.log("res:", res); // res: hahahaha
    return new Promise((resolve, reject) => {
      resolve("hehehehe");
    });
  })
  .then((res) => {
    console.log("res:", res); // res: hehehehe
  });

// 3> 若返回的值是一个对象,并且实现了thenable接口
new Promise((resolve, reject) => {
  resolve({
    then: (resolve, reject) => {
      resolve("aaaaaaa");
    },
  });
})
  .then((res) => {
    console.log("res:", res); // res: aaaaaaa
    return {
      then: function (resolve, reject) {
        resolve("bbbbbb");
      },
    };
  })
  .then((res) => {
    console.log("res:", res); // res: bbbbbb
  });

catch方法

触发catch方法执行的两种方式

// 1、通过reject参数,抛出错误
const promise1 = new Promise((resolve, reject) => {
  reject("error message1");
});
promise1.catch((err) => {
  console.log("err:", err); // err: error message1
});

// 2、throw抛出错误
const promsie2 = new Promise((resolve, reject) => {
  throw new Error("error message2");
});
promsie2.catch((err) => {
  console.log("err:", err); // 节选(因为throw抛出错误,会打印出调用栈,打印信息太多): Error: error message2
});

注意catch的回调函数内一样是一个Promsie,但是后续想要捕获需要then内捕获

catch回调函数内的返回值情况和then内的返回值情况一样

因为catch回调函数返回的不是 抛出错误了

new Promise((resolve, reject) => {
  reject("error message1");
})
  .catch((err) => {
    console.log("err:", err); // err: error message1
    return "error message2"; // 实际上是 Promise.resolve("error message2")
  })
  .catch((err) => {
    console.log("err:", err);
  });

finally方法

finally方法一般放在最后,用于做一些清除工作,无论Promise处于什么状态,都会调用finally上的回调函数。

new Promise((resolve, reject) => {
  resolve("hahaha");
})
  .then((res) => {
    console.log("res:", res); // res: hahaha
  })
  .finally(() => {
    console.log("我是最后执行的~"); // 我是最后执行的~
  });

new Promise((resolve, reject) => {
  reject("error message");
})
  .catch((err) => {
    console.log("err:", err); // err: error message
  })
  .finally(() => {
    console.log("我是最后执行的~"); // 我是最后执行的~
  });

Promise类方法

resolve方法

Promise.resolve()传的参数也有三种情况,和Promise的resolve参数的情况一致

const promise1 = Promise.resolve("fzb");
promise1.then((res) => {
  console.log("res:", res); // res: fzb
});
// Promise.resolve 等价于
new Promise((resolve, reject) => {
  resolve("fzb");
});

reject方法

传入的参数无论是什么形态,都会直接作为reject状态的参数传递到catch的回调函数参数内

const promise = Promise.reject("error message");
promise.catch((err) => {
  console.log("err:", err); // err: error message
});

// Promise.reject等价于
new Promise((resolve, reject) => {
  reject("error message");
});

all方法

将多个Promise包裹在一起形成一个新的Promsie

  • 当所有的Promsie对象的状态为fulfilled时,新的Promise对象才会为fulfilled状态

  • 当存在一个Promsie对象的状态为rejected时,新的Promise对象就是rejected状态

const p1 = new Promise((resolve, reject) => {
  resolve("p1");
});
const p2 = new Promise((resolve, reject) => {
  resolve("p2");
});
const p3 = new Promise((resolve, reject) => {
  reject("err p3");
});

Promise.all([p1, p2])
  .then((res) => {
    // res内元素的顺序与all传入的顺序有关
    console.log("res:", res); // res: [ 'p1', 'p2' ]
  })
  .catch((err) => {
    console.log("err:", err);
  });
Promise.all([p1, p2, p3])
  .then((res) => {
    console.log("res:", res);
  })
  .catch((err) => {
    // 返回第一个rejected状态的值
    console.log("err:", err); // err: err p3
  });

allSettled方法

ES11(ES2020)新添加方法,不管传入的Promsie对象最终的状态是什么,新的Promsie总是fulfilled

const p1 = new Promise((resolve, reject) => {
  resolve("p1");
});
const p2 = new Promise((resolve, reject) => {
  resolve("p2");
});
const p3 = new Promise((resolve, reject) => {
  reject("err p3");
});

Promise.allSettled([p1, p2, p3]).then((res) => {
  console.log("res:", res);
});
/** 打印结果:
   res: [
    { status: 'fulfilled', value: 'p1' },
    { status: 'fulfilled', value: 'p2' },
    { status: 'rejected', reason: 'err p3' }
  ]
 */

race方法

传入的Promise数组中,哪个Promise对象的状态最先变化(无论变成fulfilled还是rejected),就返回哪个Promsie对象的结果

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p1");
  }, 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("p2");
  }, 2000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("err p3");
  }, 3000);
});
Promise.race([p1, p2, p3])
  .then((res) => {
    console.log("res:", res); // res: p1
  })
  .catch((err) => {
    console.log("err:", err);
  });

any方法

传入的Promise数组中,哪个Promise对象的状态最先变化成fulfilled,就返回哪个Promsie对象的结果

const p1 你不知道的Promise细节

读书笔记-你不知道的JS中-promise

你不知道的JavaScript--大白话讲解Promise

你不知道的JavaScript--Item34 大白话解说Promise

VSCode自定义代码片段12——JavaScript的Promise对象

VSCode自定义代码片段12——JavaScript的Promise对象