Promise 将异步操作队列化,按照期望的顺序执行,返回符合预期的结果 Promise 是封装了回调的 原子任务
异步状态
pending
初始等待状态,初始化 promise 时的状态
* promise 没有使用 resolve 或 reject 更改状态时,状态为 pending
var pending = new Promise((resolve, reject) => {});console.log(pending); // Promise {<pending>}
fulfilled
已经解决
* promise 使用 resolve 更改状态时,状态为 fulfilled
var fulfilled = new Promise((resolve, reject) => {resolve("result");});console.log(fulfilled); // Promise {<fulfilled>: "result"}
rejected
拒绝处理
* promise 使用 reject 更改状态时,状态为 rejected
var rejected = new Promise((resolve, reject) => {reject("error");});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 }
var promise = new Promise((resolve, reject) => {var random = Math.random();if (random >= 0 && random < 0.5) resolve("fulfilled");if (random >= 0.5 && random < 1) reject("rejected");});var obj = promise.then((data) => console.log(data), // "fulfilled"(error) => console.log(error) // "rejected");console.log(obj); // Promise {<pending>}
* 若 then 没有处理 promise 传递的值,则会一直向后传递
* 若 then 已经处理 promise 传递的值,参数不会再向后传递
* 每个 then 都是全新的 promise,上一个 promise 状态不会影响以后 then 的返回状态
* 若 then 中返回 promise,后面的 then 就是对返回的 promise 的处理,需要等待返回的 promise 变更状态后才执行
var promise = new Promise((resolve, reject) => {resolve("fulfilled");});promise.then().then((data) => console.log(data)) // "fulfilled".then((data) => console.log(data)) // undefined.then((data) => {return new Promise((resolve, reject) => resolve("data"));}).then((data) => console.log(data)); // "data"
链式操作
* 上一个 then 中返回接收的 promise 的值,后面一个 then 中也会接收到 promise 的值
var promise = new Promise((resolve, reject) => {resolve("fulfilled");});promise.then((data) => {console.log(data); // "fulfilled"return data;}).then((data) => {console.log(data); // "fulfilled"});
Thenables
* 内置 then 方法时,该对象是一个 promise
* 内置 then 方法时,系
var promiseFn = {name: "zhangsan",then: function(resolve, reject) {resolve("我是属性方法");}};promiseFn.then((data) => console.log(data)); // "我是属性方法"
* 当内置 then 属性时,该对象不是 promise
* 当 then 中返回内置 then 属性的对象时,返回值是该对象
var promiseObj = {name: "lisi",then: "我是属性值"};new Promise((resolve, reject) => resolve()).then(() => {return promiseObj;}).then((data) => console.log(data)); // { name: "lisi", then: "我是属性值" }
catch
统一处理前面发生的错误 可以捕获之前所有 promise 错误处理。建议放在最后面
* catch 只捕获第一个发现的错误,发现错误时会造成阻塞
* catch 是冒泡操作,then 中若不捕获异常,将一直冒泡至 catch 中
* catch 也可以捕获 then 抛出的错误
* catch 也可以捕获 promise 中抛出的错误
* catch 也可以捕获其他错误
**
var promise = new Promise((resolve, reject) => {throw new Error("promise error");reject("error");});promise.then(() => {throw new Error("then error");}).catch((e) => console.log(e)); // Error: promise error
finally
无论 promise 何种状态,都会执行 finally promise 结束时执行,最后执行 finally
* 无参数
var promise = new Promise((resolve, reject) => {resolve();});promise.then(() => {}).catch((e) => {}).finally(() => {});
unhandledrejection 了解,不常用
监听 promise 中未处理的错误
* 已通过 onRejected 或 catch 捕获的错误无法监听
var promise = new Promise((resolve, reject) => {reject("error")});window.addEventListener("unhandledrejection", function(e) {console.log(e.promise); // 产生错误的 promise 对象console.log(e.reason); // 产生的错误});promise.then(() => {});
API
Promise.resolve(value)
**_desc_**Promise fulfilled 简写_**params**_{ any } value Promise fulfilled 返回的值_**return**_{ Promise }
Promise.resolve("ok").then((data) => console.log(data)); // "ok"
Promise.reject(value)
**_desc_**Promise rejected 简写_**params**_{ any } value Promise rejected 返回的值_**return**_{ Promise }
Promise.reject("error").catch((error) => console.log(error)); // "error"
Promise.all([...promise])
* then 接收的参数是每一个 promise fulfilled 传递的值组成的数组
* catch 只捕获第一个错误
**_desc_**批量执行 Promise_**params**_{ Promise } promise 批量处理的 promise_**return**_{ Promise }
Promise.all([Promise.reject("err - 1"),Promise.reject("err - 2"),]).catch((error) => console.log(error)); // "err - 1"Promise.all([Promise.resolve("a"),Promise.resolve("b"),Promise.resolve("c"),]).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 }
Promise.allSettled([Promise.resolve("a"),Promise.resolve("b"),Promise.resolve("c"),Promise.reject("err - 1"), // 被忽略Promise.reject("err - 2"), // 被忽略]).then((datas) => console.log(datas));/*** [* { status: "fulfilled", value: "a" },* { status: "fulfilled", value: "b" },* { status: "fulfilled", value: "c" },* { status: "rejected", reason: "err - 1" },* { status: "rejected", reason: "err - 2" },* ]*/
Promise.race([...promise])
* 返回的最快响应的 promise 的值
**
**_desc_**批量执行 Promise,返回最先响应的值_**params**_{ Promise } promise 批量处理的 promise_**return**_{ Promise }
var promise1 = new Promise((resolve, reject) => {setTimeout(() => resolve("a"), 500);});var promise2 = new Promise((resolve, reject) => {setTimeout(() => resolve("a"), 1000);});var promise3 = new Promise((resolve, reject) => {setTimeout(() => resolve("a"), 1500);});Promise.race([promise1,promise2,promise3,]).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
function queue(nums) {let promise = Promise.resolve();nums.map(i => {promise = promise.then(() => {return new Promise((resolve, reject) => {console.log(i);resolve();});});});}queue([1, 2, 3, 4, 5]); // 1 ---> 2 ---> 3 ---> 4 ---> 5
reduce
function queue(nums) {return nums.reduce((promise, i) => {return promise.then(() => {return new Promise((resolve, reject) => {console.log(i);resolve();});});}, Promise.resolve());}queue([1, 2, 3, 4, 5]);
async / await 👍
async / await 是 promise 的语法糖 避免回调地狱(callback hell)
* async / await 本质还是 promise,只是更简介的语法糖书写方式
* async / await 可以让 promise 更加清晰易懂,解决回调嵌套等问题
async
* async 放置于函数前方
* 在函数前使用 async 后,函数将返回 promise
async function fn1() {return "fn1";}const fn2 = async () => {return "fn2"};console.log(fn1()); // Promise {<fulfilled>: "fn1"}console.log(fn2()); // Promise {<fulfilled>: "fn2"}
await
* await 必须放在 async 定义的函数中使用**
async function awaitDemo() {let promise = new Promise((resolve, reject) => {setTimeout(() => {resolve("Hello World");}, 2500)});let result = await promise;console.log(result); // 延时 2500ms 打印输出 "Hello World"}awaitDemo();
* await 后方一般是 promise,如何不是 promise 则按照同步执行
async function awaitDemo() {let fn = () => console.log("Hello World");const result = await fn();console.log(result); // await 后方是普通函数,不是 promise, 直接执行函数并返回结果}awaitDemo();
* await 也可以操作 thenables 对象
class User {name = "zhangsan";then(resolve, reject) {setTimeout(() => {console.log(this.name);}, 2500);}}async function getName() {const name = await new User();console.log(name);}getName(); // 延时 2500ms 打印输出 "zhangsan"
try...catch
用于捕获 async / await 中抛出的错误
**
function timeout(timeout) {return new Promise((resolve, reject) => {setTimeout(() => {var random = Math.random();if (random >= 0 && random < 0.5) {resolve("fulfilled");} else {reject("rejected");}}, timeout)});}async function tryCatch() {try {console.log(await timeout(500));console.log(await timeout(1000));console.log(await timeout(1500));} catch (e) {console.error(e);}}tryCatch();
* 对已捕获的错误进行处理后,可以解除错误导致的阻塞
function timeout(timeout) {return new Promise((resolve, reject) => {setTimeout(() => {var random = Math.random();if (random >= 0 && random < 0.5) {resolve("fulfilled");} else {reject("rejected");}}, timeout)});}async function tryCatch() {try {console.log(await timeout(500));} catch (e) {console.error(e);}try {console.log(await timeout(1000));} catch (e) {console.error(e);}try {console.log(await timeout(1500));} catch (e) {console.error(e);}}tryCatch();
