JS Promise 的一些理解
JS Promise
简介
Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。(MDN的定义)
什么是 JS 的异步操作 ?
为什么要使用Promise ?
解决“回调地狱”,使代码更加清晰、易于维护
举个例子,现在我需要通过src动态加载一个JS脚本
function loadScript(src) {
// 创建一个 <script> 标签,并将其附加到页面
// 这将使得具有给定 src 的脚本开始加载,并在加载完成后运行
let script = document.createElement('script');
script.src = src;
document.head.append(script);
}
当然我希望了解脚本何时加载完成,以使用其中的新函数和变量。但是我在外部获取不到函数内部的变量,所以必须给给他加上一个回调函数。
function loadScript(src, callback) {
let script = document.createElement("script");
script.src = src;
document.head.append(script);
// 当脚本挂载成功后调用callback(null,script);
script.onload = () => callback(null, script);
// 当脚本挂载失败后调用callback(new Error(`Script load error for ${src}`));
script.onerror = () => callback(new Error(`Script load error for ${src}`));
}
loadScript("./src.js", (error, script) => {
if (error) { //处理error
console.log(error);
} else {
console.log("success");
}
});
当我需要继续依次加载多个脚本,那么代码会变成这样。
loadScript("./src.js", (error, script) => {
if (error) {
console.log(error);
} else {
loadScript("./src.js", (error, script) => {
if (error) {
console.log(error);
} else {
loadScript("./src.js", (error, script) => {
if (error) {
console.log(error);
} else {
console.log("success");
}
});
}
});
}
});
代码会逐渐向右缩进,不利于维护和阅读。这就是我们所说的“回调地狱”。
Promise的基本使用
创建一个Promise对象
Promise 对象的构造器(constructor)语法如下:
let promise = new Promise((resovle, reject) => {
//executor(执行者)
})
- 传递给 new Promise 的函数被称为 executor。当 new Promise 被创建,executor 会立刻自动运行。
- 一个 Promise 对象有 PromiseState , PromiseResult 两个属性:
- PromiseState (state)有三个状态:
- pending: 初始状态
- fulfilled: 操作成功
- rejected: 操作失败
如果一个 promise 已经被兑现(fulfilled)或被拒绝(rejected),那么我们也可以说它处于已敲定(settled)状态
- PromiseResult (result)的初始值是 undefine
- PromiseState (state)有三个状态:
- resovle和reject是JS自身提供的回调函数
- 当 resovle(value) 被调用后, state: pending --> fulfilled,result: undefine --> value
- 当 reject(error) 被调用或抛出异常后, state: pending --> rejected, result: undefine --> error
注意: 如果 value 是一个Promise对象的话 , 会直接返回该Promise对象
代码如下:
let promise = new Promise((resovle, reject) => {
resovle(value); //state: pending --> fulfilled,result: undefine --> value
reject(error)); //state: pending --> rejected, result: undefine --> error
throw new Error("error"); //state: pending --> rejected, result: undefine --> new Error("error")
});
then,catch,finally 方法
当Promise对象处于 settled (fulfille或rejected)状态时,这三个方法可以对Promise进行进一步的操作。
then(handleFulfilled, handleRejected)
then是最重要的一个方法,catch和finally可以看做是它的变形。语法如下:
promise.then(
(value) => {},//如果state:fulfilled, 执行第一个回调
(error) => {}//如果state:rejected, 执行第二个回调
);
//回调函数的参数(value或error)的值为Promise的result属性的值
当我们只关心fulfilled状态的话(一般的用法,通常会用catch来捕捉error),我们可以只传入一个回调,像这样:
promise.then(
(value) => {},//如果state:fulfilled, 执行回调
);
catch(handleRejected)
语法如下:
promise.catch(
(error) => {}//如果state:rejected, 执行回调
);
//error的值为Promise的result属性的值
可以看出来catch其实和then差不多,但是它只能在rejected状态下执行
finally(handleRejected)
语法如下:
promise.finally(
() => {}//如果state:fulfilled或state:rejected, 执行回调
);
//回调不需要参数,只要Promise对象处于settle状态就可以执行
//finally 不能获取Promise对象的result属性
Promise 链
三个方法都是异步操作的并且会默认返回一个Promise对象
那返回的Promise对象是怎样的呢?看代码和注释
let promise = new Promise((resolve, reject)=>{
resolve(1);
})
// 一、回调函数抛出异常 --> state: rejected,result: new Error("error")
// 二、回调函数不抛出抛出异常
// 1.回调函数无返回值 --> state: fullfilled,result: undefine
// 1.回调函数有返回值(value) --> state: fullfilled,result: value
// 注意:如果返回值是Promise对象,会直接返回该Promise对象
let promise1 = promise.then(
(value) => {
throw new Error("error"); // state: rejected,result: new Error("error")
return 1; // state: fullfilled,result: 1
},
(error) => {}
);
catch的返回值和then是一样的
catch就是一个没有第一个回调函数的then

浙公网安备 33010602011771号