前言
上一篇章我们学习了Promise的概念、基本使用、状态等等,对于Promise也有了基础的了解,那本章就对与Promise的方法作基本学习,去了解了解Promise提供了什么方法。
一、then
then
处理Promise
返回结果,接收两个回调函数
- 第一个回调函数:Promise执行成功触发的回调函数,从这个函数中可以获取成功数据
- 第二个回调函数:Promise执行失败或出错触发的回调函数
在异步代码中我们需要传入回调函数来获取返回结果,而想通过这个结果再进行异步操作,就需要继续执行同样的操作,这样就产生了回调地狱
,如下展示
sum(10, 20, (result) => {
console.log("执行结果1", result);
sum(result, 30, () => {
console.log("执行结果2", result);
sum(result, 40, () => {
console.log("执行结果3", result);
sum(result, 50, () => {
console.log("执行结果4", result);
sum(result, 60, () => {
console.log("执行结果5", result);
console.log("执行结束");
});
});
});
});
});
这样的代码就会导致我们难以处理某个回调产生的问题、可读性差等问题,那Promise又是如何去解决的?
在调用then
方法之后会返回一个Promise对象,而基于这个Promise对象可以再调用then
方法,实现链式调用,也就解决回调地狱
问题,光讲概念有点难以理解,上代码
function sum(a, b) {
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b);
}, 2000);
});
}
sum(10, 20)
.then((result) => {
// 触发成功回调
console.log("执行结果1", result);
return result + 30;
},(err) => {
// 触发错误回调
console.log("出错啦!!");
}).then((result) => {
// 触发成功回调
console.log("执行结果2", result);
return result + 40;
},(err) => {
// 触发错误回调
console.log("出错啦!!");
});
在then
方法中,通过第一个函数可以获取到异步代码成功返回的方法,那在这个函数中我们就可以做一些其他到操作,然后继续返回结果,成为下一个then
方法成功回调的数据,也就是说我们在每个then
方法的两个回调单独做操作,成功回调继续求和返回结果,错误回调则处理错误。
二、catch
catch
是在Promise对象中执行reject函数
或执行出错
所触发的,为了捕获错误并返回错误结果,同样执行catch
方法也会返回一个Promise对象。
catch
接收一个回调函数,并接收一个参数,里面存储着错误信息
或异常对象
情况一:通过reject
方法触发,可以获取reject
所存储的数据
function fun() {
return new Promise((resolve, reject) => {
reject("异步代码执行出错啦!!");
});
}
fun().catch((error) => {
console.log(error);
});
情况二:代码执行出现错误,则可以获取到异常错误信息
function fun() {
return new Promise((resolve, reject) => {
throw new Error("你的代码有Bug");
reject("异步代码执行出错啦!!");
});
}
fun().catch((error) => {
console.log(error);
});
三、finally
finally
:最终的,Promise对象无论结果是成功还是失败都会触发的回调函数,不过这个函数用的比较少,可以作了解。
成功情况
function fun() {
return new Promise((resolve, reject) => {
resolve("success");
});
}
fun().finally(() => {
console.log("成功啦");
});
失败情况
function fun() {
return new Promise((resolve, reject) => {
reject("error");
});
}
fun().finally(() => {
console.log("你阻止不了我的,JOJO");
});
四、all
Promise.all()
将多个Promise实例,包装一个新的Prmise实例。面试问过
const p = Promise.all([p1, p2, p3]);
p的状态由【p1, p2, p3】决定,分以下两种情况
- 情况一:p1, p2, p3都执行成功,p的状态才会是成功的,p的成功数据由
p1, p2, p3
的成功数据组合而成 - 情况二:p1, p2, p3其他一个执行失败,那么p的状态就会是失败的,p失败回调的数据由最先失败的Promise实例决定
业务场景
- 需要等待三个异步执行完成才会继续往下执行,当然可以通过async、await去实现,但是这样会导致其他异步等待这一个异步代码执行完成才会执行,这样就会耗费较多的时间,导致用户体验不好,这就可以使用到
Promise.all()
方法,等执行完成里面的方法才会往下执行
模拟所述业务场景,创建三个异步函数,当做三个请求,每个请求时长一秒钟
function ajax1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("请求1的数据");
resolve("请求1的数据");
}, 1000);
});
}
function ajax2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("请求2的数据");
resolve("请求2的数据");
}, 1000);
});
}
function ajax3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("请求3的数据");
resolve("请求3的数据");
}, 1000);
});
}
未使用Promise.all()
所需时间:3011
const btn = document.getElementById("btn");
btn.addEventListener("click", async () => {
console.log("开始执行");
const start = Date.now();
await ajax1();
await ajax2();
await ajax3();
const end = Date.now() - start;
console.log("执行结束,所用时间", end);
});
使用Promise.all()
后,执行时间:1013
,对比未使用,少了三倍
btn.addEventListener("click", async () => {
console.log("开始执行");
const start = Date.now();
await Promise.all(ajax1(), ajax2(), ajax3());
const end = Date.now() - start;
console.log("执行结束,所用时间", end);
});
五、race
Promise.race()
方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
const promise = Promise.race([p1, p2, p3])
但不同的是,在p1,、p2、p3中谁最先
返回的,那么这个promise
状态就由它决定,返回值也是由它决定
例子,如果有一个Promise实例失败,那么结束了。
- 比如三个人比赛跑步,谁先跑到终点,谁就能拿到金牌,拥有金牌的所有权
代码演示
依旧是模拟三个请求,但是设置不同的请求时长
function ajax1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("请求1");
}, 1000);
});
}
function ajax2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("请求2");
}, 2000);
});
}
function ajax3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("请求3");
}, 3000);
});
}
使用方法
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
console.log("开始执行");
const p = Promise.race([ajax1, ajax2, ajax3]);
p.then((res) => {
console.log("谁是金牌:", res);
});
console.log("执行结束");
});
六、allSettled
Promise.allSettled()
也是将多个Promise实例包装成一个新的Promise实例,但不同的是,它会等这些Promise实例都执行结束,无论状态是成功还是失败,包装实例才会结束。
返回结果由多个Promise实例结果组成
业务场景
- 不关心请求返回的结果,只关心请求是否完成
function ajax1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("请求1");
}, 1000);
});
}
function ajax2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("请求2");
}, 2000);
});
}
function ajax3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("请求3");
}, 3000);
});
}
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
console.log("开始执行");
const p = Promise.allSettled([ajax1, ajax2, ajax3]);
p.then((res) => {
console.log("结果", res);
});
console.log("执行结束");
});
七、any
Promise.any()
也是接收一组Promise实例作为参数,然后返回一个新的Promise实例,它与race
有些类似,但它不会因为一个Promise实例失败就结束。
const p = Promise([p1, p2, p3])
一组Promise实例中,只要有一个Promise实例成功,那么包装实例的状态就是成功的;如果所有参数Promise实例都失败,那么包装实例就是失败的
只要一个成功,那么包装实例就是成功的,返回结果由最先成功的Promise实例决定
function ajax1() {
return new Promise((resolve, reject) => {
resolve("成功请求1");
});
}
function ajax2() {
return new Promise((resolve, reject) => {
resolve("成功请求2");
});
}
function ajax3() {
return new Promise((resolve, reject) => {
resolve("成功请求3");
});
}
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
console.log("开始执行");
const p = Promise.any([ajax1, ajax2, ajax3]);
p.then((res) => {
console.log("结果", res);
});
console.log("执行结束");
});
所有都失败,包装实例才是失败的,返回结果由最先失败的Promise实例决定
function ajax1() {
return new Promise((resolve, reject) => {
reject("请求1");
});
}
function ajax2() {
return new Promise((resolve, reject) => {
reject("请求2");
});
}
function ajax3() {
return new Promise((resolve, reject) => {
reject("请求3");
});
}
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
console.log("开始执行");
const p = Promise.any([ajax1, ajax2, ajax3]);
p.then((res) => {
console.log("结果", res);
});
console.log("执行结束");
});