你不知道的Promise细节
Posted 还是不会呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你不知道的Promise细节相关的知识,希望对你有一定的参考价值。
你不知道的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上的方法存在三个:
then
、catch
和finally
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细节
你不知道的JavaScript--Item34 大白话解说Promise