Promise 将异步操作队列化,按照期望的顺序执行,返回符合预期的结果 Promise 是封装了回调的 原子任务


异步状态

* 状态一旦改变将不可更改

pending

初始等待状态,初始化 promise 时的状态

* promise 没有使用 resolve 或 reject 更改状态时,状态为 pending

  1. var pending = new Promise((resolve, reject) => {});
  2. console.log(pending); // Promise {<pending>}

fulfilled

已经解决

* promise 使用 resolve 更改状态时,状态为 fulfilled

  1. var fulfilled = new Promise((resolve, reject) => {
  2. resolve("result");
  3. });
  4. console.log(fulfilled); // Promise {<fulfilled>: "result"}

rejected

拒绝处理

* promise 使用 reject 更改状态时,状态为 rejected

  1. var rejected = new Promise((resolve, reject) => {
  2. reject("error");
  3. });
  4. console.log(rejected); // Promise {<rejected>: "error"}

then

用于定义当 promise 状态发生改变时的处理

* promise 处理异步操作,then 获取结果
* 一个 Promise 必须有一个 then 方法用于处理状态改变

promise.then(onFulfilled, onRejected)

* onFulfilled 或 onRejected 不是函数将被忽略
* 两个回调函数只会被调用一次

_**params**_ { object } promise Promise 对象 _**params**_ { function } onFulfilled 处理 fulfilled 状态的回调函数 _**params**_ { function } onRejected 处理 rejected 状态的回调函数 _**return**_ { Promise }

  1. var promise = new Promise((resolve, reject) => {
  2. var random = Math.random();
  3. if (random >= 0 && random < 0.5) resolve("fulfilled");
  4. if (random >= 0.5 && random < 1) reject("rejected");
  5. });
  6. var obj = promise
  7. .then(
  8. (data) => console.log(data), // "fulfilled"
  9. (error) => console.log(error) // "rejected"
  10. );
  11. console.log(obj); // Promise {<pending>}

* 若 then 没有处理 promise 传递的值,则会一直向后传递
* 若 then 已经处理 promise 传递的值,参数不会再向后传递
* 每个 then 都是全新的 promise,上一个 promise 状态不会影响以后 then 的返回状态
* 若 then 中返回 promise,后面的 then 就是对返回的 promise 的处理,需要等待返回的 promise 变更状态后才执行

  1. var promise = new Promise((resolve, reject) => {
  2. resolve("fulfilled");
  3. });
  4. promise
  5. .then()
  6. .then((data) => console.log(data)) // "fulfilled"
  7. .then((data) => console.log(data)) // undefined
  8. .then((data) => {
  9. return new Promise((resolve, reject) => resolve("data"));
  10. })
  11. .then((data) => console.log(data)); // "data"


链式操作

* 上一个 then 中返回接收的 promise 的值,后面一个 then 中也会接收到 promise 的值

  1. var promise = new Promise((resolve, reject) => {
  2. resolve("fulfilled");
  3. });
  4. promise
  5. .then((data) => {
  6. console.log(data); // "fulfilled"
  7. return data;
  8. })
  9. .then((data) => {
  10. console.log(data); // "fulfilled"
  11. });


Thenables

* 内置 then 方法时,该对象是一个 promise
* 内置 then 方法时,系

  1. var promiseFn = {
  2. name: "zhangsan",
  3. then: function(resolve, reject) {
  4. resolve("我是属性方法");
  5. }
  6. };
  7. promiseFn
  8. .then((data) => console.log(data)); // "我是属性方法"

* 当内置 then 属性时,该对象不是 promise
* 当 then 中返回内置 then 属性的对象时,返回值是该对象

  1. var promiseObj = {
  2. name: "lisi",
  3. then: "我是属性值"
  4. };
  5. new Promise((resolve, reject) => resolve())
  6. .then(() => {
  7. return promiseObj;
  8. })
  9. .then((data) => console.log(data)); // { name: "lisi", then: "我是属性值" }

catch

统一处理前面发生的错误 可以捕获之前所有 promise 错误处理。建议放在最后面

* catch 只捕获第一个发现的错误,发现错误时会造成阻塞
* catch 是冒泡操作,then 中若不捕获异常,将一直冒泡至 catch 中
* catch 也可以捕获 then 抛出的错误
* catch 也可以捕获 promise 中抛出的错误
* catch 也可以捕获其他错误
**

  1. var promise = new Promise((resolve, reject) => {
  2. throw new Error("promise error");
  3. reject("error");
  4. });
  5. promise
  6. .then(() => {
  7. throw new Error("then error");
  8. })
  9. .catch((e) => console.log(e)); // Error: promise error

finally

无论 promise 何种状态,都会执行 finally promise 结束时执行,最后执行 finally

* 无参数

  1. var promise = new Promise((resolve, reject) => {
  2. resolve();
  3. });
  4. promise
  5. .then(() => {})
  6. .catch((e) => {})
  7. .finally(() => {});

unhandledrejection 了解,不常用

监听 promise 中未处理的错误

* 已通过 onRejected 或 catch 捕获的错误无法监听

  1. var promise = new Promise((resolve, reject) => {
  2. reject("error")
  3. });
  4. window.addEventListener("unhandledrejection", function(e) {
  5. console.log(e.promise); // 产生错误的 promise 对象
  6. console.log(e.reason); // 产生的错误
  7. });
  8. promise
  9. .then(() => {});

API

Promise.resolve(value)

**_desc_** Promise fulfilled 简写 _**params**_ { any } value Promise fulfilled 返回的值 _**return**_ { Promise }

  1. Promise.resolve("ok")
  2. .then((data) => console.log(data)); // "ok"

Promise.reject(value)

**_desc_** Promise rejected 简写 _**params**_ { any } value Promise rejected 返回的值 _**return**_ { Promise }

  1. Promise.reject("error")
  2. .catch((error) => console.log(error)); // "error"

Promise.all([...promise])

* then 接收的参数是每一个 promise fulfilled 传递的值组成的数组
* catch 只捕获第一个错误

**_desc_** 批量执行 Promise _**params**_ { Promise } promise 批量处理的 promise _**return**_ { Promise }

  1. Promise.all([
  2. Promise.reject("err - 1"),
  3. Promise.reject("err - 2"),
  4. ])
  5. .catch((error) => console.log(error)); // "err - 1"
  6. Promise.all([
  7. Promise.resolve("a"),
  8. Promise.resolve("b"),
  9. Promise.resolve("c"),
  10. ])
  11. .then((datas) => console.log(datas)); // ["a", "b", "c"]

Promise.allSettled([...promise])

* allSettled 将 fulfilled 和 rejected 状态的值都传递到 then 中
* then 接收的参数是每一个 promise 传递的值组成的数组
* fulfilled 传递值格式:**{status: "fulfilled", value: ""}**
* rejected 传递值格式:**{status: "rejected", reason: ""}**

*
此时的 catch 无效**

**_desc_** 批量执行 Promise fulfilled _**params**_ { Promise } promise 批量处理的 promise _**return**_ { Promise }

  1. Promise.allSettled([
  2. Promise.resolve("a"),
  3. Promise.resolve("b"),
  4. Promise.resolve("c"),
  5. Promise.reject("err - 1"), // 被忽略
  6. Promise.reject("err - 2"), // 被忽略
  7. ])
  8. .then((datas) => console.log(datas));
  9. /**
  10. * [
  11. * { status: "fulfilled", value: "a" },
  12. * { status: "fulfilled", value: "b" },
  13. * { status: "fulfilled", value: "c" },
  14. * { status: "rejected", reason: "err - 1" },
  15. * { status: "rejected", reason: "err - 2" },
  16. * ]
  17. */

Promise.race([...promise])

* 返回的最快响应的 promise 的值
**

**_desc_** 批量执行 Promise,返回最先响应的值 _**params**_ { Promise } promise 批量处理的 promise _**return**_ { Promise }

  1. var promise1 = new Promise((resolve, reject) => {
  2. setTimeout(() => resolve("a"), 500);
  3. });
  4. var promise2 = new Promise((resolve, reject) => {
  5. setTimeout(() => resolve("a"), 1000);
  6. });
  7. var promise3 = new Promise((resolve, reject) => {
  8. setTimeout(() => resolve("a"), 1500);
  9. });
  10. Promise.race([
  11. promise1,
  12. promise2,
  13. promise3,
  14. ])
  15. .then((data) => console.log(data)); // "a", 第一个倒计时最短,执行第一个

Promise.any([...promise])

* ES12(ES2021)新特性
* 当 Promise 列表中任意 Promise 成功 resolve,则返回最快 resolve 的结果状态
* 当 Promise 列表中所有 Promise 失败 reject,则抛出异常表示所有请求失败

**_desc_** 批量执行 Promise _**params**_ { Promise } promise 批量处理的 promise _**return**_ { Promise }

任务队列

本质:在 Promise.then() 中返回新的 Promise,使 Promise 依次进行

map

  1. function queue(nums) {
  2. let promise = Promise.resolve();
  3. nums.map(i => {
  4. promise = promise.then(() => {
  5. return new Promise((resolve, reject) => {
  6. console.log(i);
  7. resolve();
  8. });
  9. });
  10. });
  11. }
  12. queue([1, 2, 3, 4, 5]); // 1 ---> 2 ---> 3 ---> 4 ---> 5

reduce

  1. function queue(nums) {
  2. return nums.reduce((promise, i) => {
  3. return promise.then(() => {
  4. return new Promise((resolve, reject) => {
  5. console.log(i);
  6. resolve();
  7. });
  8. });
  9. }, Promise.resolve());
  10. }
  11. queue([1, 2, 3, 4, 5]);

async / await 👍

async / await 是 promise 的语法糖 避免回调地狱(callback hell)

* async / await 本质还是 promise,只是更简介的语法糖书写方式
* async / await 可以让 promise 更加清晰易懂,解决回调嵌套等问题

async

* async 放置于函数前方
* 在函数前使用 async 后,函数将返回 promise

  1. async function fn1() {
  2. return "fn1";
  3. }
  4. const fn2 = async () => {
  5. return "fn2"
  6. };
  7. console.log(fn1()); // Promise {<fulfilled>: "fn1"}
  8. console.log(fn2()); // Promise {<fulfilled>: "fn2"}

await


*
await 必须放在 async 定义的函数中使用**

  1. async function awaitDemo() {
  2. let promise = new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. resolve("Hello World");
  5. }, 2500)
  6. });
  7. let result = await promise;
  8. console.log(result); // 延时 2500ms 打印输出 "Hello World"
  9. }
  10. awaitDemo();

* await 后方一般是 promise,如何不是 promise 则按照同步执行

  1. async function awaitDemo() {
  2. let fn = () => console.log("Hello World");
  3. const result = await fn();
  4. console.log(result); // await 后方是普通函数,不是 promise, 直接执行函数并返回结果
  5. }
  6. awaitDemo();

* await 也可以操作 thenables 对象

  1. class User {
  2. name = "zhangsan";
  3. then(resolve, reject) {
  4. setTimeout(() => {
  5. console.log(this.name);
  6. }, 2500);
  7. }
  8. }
  9. async function getName() {
  10. const name = await new User();
  11. console.log(name);
  12. }
  13. getName(); // 延时 2500ms 打印输出 "zhangsan"

try...catch

用于捕获 async / await 中抛出的错误

**

  1. function timeout(timeout) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. var random = Math.random();
  5. if (random >= 0 && random < 0.5) {
  6. resolve("fulfilled");
  7. } else {
  8. reject("rejected");
  9. }
  10. }, timeout)
  11. });
  12. }
  13. async function tryCatch() {
  14. try {
  15. console.log(await timeout(500));
  16. console.log(await timeout(1000));
  17. console.log(await timeout(1500));
  18. } catch (e) {
  19. console.error(e);
  20. }
  21. }
  22. tryCatch();

* 对已捕获的错误进行处理后,可以解除错误导致的阻塞

  1. function timeout(timeout) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. var random = Math.random();
  5. if (random >= 0 && random < 0.5) {
  6. resolve("fulfilled");
  7. } else {
  8. reject("rejected");
  9. }
  10. }, timeout)
  11. });
  12. }
  13. async function tryCatch() {
  14. try {
  15. console.log(await timeout(500));
  16. } catch (e) {
  17. console.error(e);
  18. }
  19. try {
  20. console.log(await timeout(1000));
  21. } catch (e) {
  22. console.error(e);
  23. }
  24. try {
  25. console.log(await timeout(1500));
  26. } catch (e) {
  27. console.error(e);
  28. }
  29. }
  30. tryCatch();