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();