学前端的大家都知道promise是重中之重,也是面试的必考项。但是刚接触promise我一直很晕头晕脑的,搜集文章前看后看基本都是讲解promise的状态它的方法就没有再深入了,以至于面试时候面试官一旦往深问我就懵了。所以今天我们就详细的说一下promise吧!!
promise是什么呢?它有什么用呢?为什么需要promise呢?
promise是什么?
promise就是一个异步编程的解决方案,ok我猜你应该没明白。gpt告诉我他是一个用来管理任务状态和结果的容器。
它有三种状态:pending,fulfilled,rejected,而且状态的变化只可以从pending-->fufilled;pending-->fufilled
promise有什么用?
这个问题就要追朔到回调函数以及js的异步机制上了。
js是单线程语言,同一时间内只能执行一个任务。如果其中一个任务执行时间很长,那么后续的任务就要等待很久才能执行。举个例子,比如你在某平台点一份外卖(1分钟),商家制作(10分钟),外卖员送餐(加入距离远需要30分钟),现在规定外卖员在商家制餐这段时间什么都不能做只能在店里等着,你在送餐这段时间什么都不能做只能等餐,你想想是不是很痛苦。现在有一种机制叫异步,异步的话就是商家制餐这段时间外卖员可以去送别的单子,等做好了通知外卖员取餐。外卖员送餐这段时间你不用干等它,你去美美的刷了半小时短视频,然后外卖到了给你打电话。画个图理解(有错误望指出,避免错误引导)
那么怎么实现异步呢?这就需要用到回调函数了!回调函数是传递给另一个函数并且在某个时机执行的函数。
不使用回调函数,同步调用
// 点外卖函数
function orderWaiMai() {
console.log('点外卖');
}
// 做外卖函数
function cookWaiMai() {
console.log('做外卖');
console.log('外卖做好了');
}
// 送外卖函数
function sendWaiMai() {
console.log('外卖员送外卖');
console.log('外卖送到了');
}
// 吃饭函数
function eat() {
console.log('可以吃饭了');
}
// 刷短视频函数
function watchVideo() {
console.log('刷短视频');
}
// 主函数
function main() {
orderWaiMai(); // 点外卖
cookWaiMai(); // 做外卖
sendWaiMai(); // 外卖送到
watchVideo(); // 刷短视频
eat(); // 可以吃饭了
}
main();
使用回调函数,异步调用
// 点外卖函数
function orderWaiMai(callback) {
console.log('点外卖');
callback(); // 点外卖完,通知开始做外卖
}
// 做外卖函数
function cookWaiMai(callback) {
console.log('做外卖');
setTimeout(() => { // 模拟做外卖的耗时,假设做外卖需要 3 秒
console.log('外卖做好了');
callback(); // 外卖做好了,通知外卖员来取
}, 3000); // 3秒后执行回调,模拟做外卖的过程
}
// 送外卖函数
function sendWaiMai(callback) {
console.log('外卖员送外卖');
setTimeout(() => { // 模拟送外卖的耗时,假设送外卖需要 2 秒
console.log('外卖送到了');
callback(); // 外卖送到,通知可以吃饭了
}, 2000); // 2秒后执行回调,模拟送外卖的过程
}
// 刷短视频函数
function watchVideo() {
console.log('刷短视频');
}
// 吃饭函数
function eat() {
console.log('可以吃饭了');
}
// 主函数
function main() {
orderWaiMai(() => {
cookWaiMai(() => {
sendWaiMai(() => {
eat();
});
});
});
watchVideo();
}
main();
我们这是执行五个任务,可以看到主函数中由于异步函数需要层层嵌套,如果是几万几十万任务呢?是不是代码就嵌套的没边了!!!这种现象就叫做回调地狱
为什么需要promise?
由上面的代码我们就可以发现为什么需要promise了吧?promise主要为了优雅的处理异步操作,它可以通过链式调用实现异步,使得代码看起来很好维护。解决回调地狱的问题。
如果用promise来写我们上面的例子的话
// 点外卖函数
function orderWaiMai() {
return new Promise((resolve) => {
console.log('点外卖');
resolve(); // 点外卖完成,触发下一个操作
});
}
// 做外卖函数
function cookWaiMai() {
return new Promise((resolve) => {
console.log('做外卖');
setTimeout(() => {
console.log('外卖做好了');
resolve(); // 做外卖完成,触发下一个操作
}, 3000);
});
}
// 送外卖函数
function sendWaiMai() {
return new Promise((resolve) => {
console.log('外卖员送外卖');
setTimeout(() => {
console.log('外卖送到了');
resolve(); // 外卖送到,触发下一个操作
}, 2000);
});
}
// 吃饭函数
function eat() {
console.log('可以吃饭了');
}
// 刷短视频函数
function watchVideo() {
console.log('刷短视频');
}
// 主函数
function main() {
orderWaiMai()
.then(cookWaiMai)
.then(sendWaiMai)
.then(eat)
.catch((error) => { // 捕获并处理任何可能的错误
console.error('发生错误:', error);
});
// 刷短视频可以在做外卖和送外卖的过程中进行
watchVideo();
}
main();
上面的代码是不是相对来说清晰明了了很多!promise使用.then方法对异步任务进行链式回调,除了.then和.catch,promise还有.all,.race等方法
.all是常考项,它接收一个包含多个promise对象的数组。它会并行执行这三个异步操作,而不是等待第一个操作完成后再执行第二个,依次类推。当所有的promise都成功完成时,Promise.all()
的 .then()
回调会被触发,并且返回一个包含所有操作结果的数组。
.race只要其中的任意一个promise完成(无论是成功还是失败),Promise.race()
就会立即返回,其他的promise会继续执行,但不会影响最终结果。
今天就写到这里吧~ 有啥错误的地方希望大家可以积极指正!!