序言
在上篇文章中我们聊到了异步
进行的利与弊,以及用回调
来处理异步
,但是这种处理方式会形成"回调地狱"
,虽不会造成内存泄漏
,但是代码复杂而且维护难度
较高。那么在今天我会为大家介绍一下ES6新增的一个对象------Promise
。
Promise概念
JavaScript作为一种单线程且异步
的语言,处理异步
操作,可能是具有挑战性的。对js执行代码
的底层逻辑
不太熟悉的朋友可以去翻翻我的这篇文章【前端面试】深入理解 JS 中 调用栈 作用域链 闭包
如何优雅地处理异步
呢?这时Promise
就发挥了作用,提供了一种更有结构和可靠的方式来处理异步代码
。接下来让我们来先对Promise
进行一个深入的认识。
Promise的基础知识
1. Promise是什么?
在JavaScript中,Promise
是一种处理异步
操作的对象
,它表示一个在未来某个时刻会完成或失败的操作。Promise
提供了更清晰、更结构化的方式来处理异步代码
,避免了回调地狱(Callback Hell)
的问题。
2. Promise的三个状态
Promise有三个状态:
- Pending(进行中) : 初始状态,表示操作正在进行中。
- Fulfilled(已成功) : 表示操作已经成功完成。
- Rejected(已失败) : 表示操作失败。
总结:
Promise
表示异步操作
的最终完成或失败。它有三个状态:进行中(Pending)
、已成功(Fulfilled)
、已失败(Rejected)
。创建Promise
时,它开始处于进行中
状态,并根据异步操作的结果转换为已成功
或已失败
状态,并且这个转换过程是不可逆的,只允许进行一次。接下来让我们再来了解一下如何创建一个Promise对象。
Promise 创建及使用方法
创建Promise对象
使用new Promise()
构造函数创建一个Promise对象。构造函数接受一个带有两个参数的函数,分别是resolve
和reject
。resolve
用于表示操作成功,reject
用于表示操作失败。
javascript
const myPromise = new Promise((resolve, reject) => {
// 异步操作
if (/* 操作成功 */) {
resolve("操作成功");
} else {
reject("操作失败");
}
});
链式使用Promise
Promise
可以链接
在一起,以更灵活地组织和控制异步操作。下面我们借助LOL全球总决赛四强的一次比赛来模拟链式
使用Promise
处理比赛进行顺序的异步
操作。
javascript
function bo1(){
return new Promise((resolve,reject) => {// promiese----ES6新增构造函数
setTimeout(() => {
console.log('JDG比赛第一把输了!');
resolve('比分0:1')
}, 2000);
})
}
function bo2(){
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('JDG比赛第二把赢了!');
resolve('比分1:1')
}, 1000)
})
}
function bo3(){
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('JDG比赛第三把输了!');
resolve('比分1:2')
}, 500)
})
}
function bo4(){
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('JDG比赛第四把输了!');
resolve('比分:1:3,坐飞机回家了!')
}, 300)
})
}
bo1()
.then((res) => {
console.log(res);
return bo2()
})
.then(res2 => {
console.log(res2);
return bo3()
})
.then(res3 => {
console.log(res3);
return bo4()
})
.then(res4 => {
console.log(res4);
})
我们去浏览器运行这段代码看看结果:
虽然每段代码执行都是异步
进行的,且每一个函数自己有不同的执行时间
,但是当我们对他们进行Promise链式调用
的时候,结果就能按照我们预期的效果进行展现,不仅如此,相比回调地狱
,Promise
还提供了各种方法来满足我们的需求。比如捕获错误,省去像无头苍蝇一般到处乱找BUG的情况。接下来我会为大家一一详细介绍常用的方法。
promise常用方法
Promise.all()
在JavaScript中,Promise.all
方法是Promise
对象上的一个静态方法,用于将多个Promise
对象包装成一个新的Promise
对象。这个新的Promise
对象的状态取决于所有原始Promise
对象的状态,只有当所有的原始Promise
对象都成功时,新的Promise
对象才会成功。让我们深入了解Promise.all
方法的语法、用法和一些示例。
1. 语法和用法
Promise.all
方法的基本语法如下:
javascript
Promise.all(iterable);
iterable
: 一个可迭代对象,通常是包含Promise
对象的数组。
Promise.all
返回一个新的Promise
对象,其状态和值取决于所有原始Promise
对象的状态。如果所有原始Promise
对象都成功,则新的Promise
对象将成功,并包含一个包含所有原始Promise
结果的数组。如果任何一个原始Promise
对象失败,则新的Promise
对象将失败,并包含第一个失败的原始Promise
对象的错误信息。
2. 示例演示
让我们通过一个简单的例子来说明Promise.all
的用法:
javascript
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2 resolved');
}, 500);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 3 resolved');
}, 800);
});
const allPromise = Promise.all([promise1, promise2, promise3]);
allPromise
.then((results) => {
console.log(results); // 所有Promise成功的结果数组
})
.catch((error) => {
console.error(error); // 第一个失败的Promise的错误信息
});
在这个例子中,
allPromise
将在promise1
、promise2
和promise3
都成功时成功。它将包含一个数组,其中包含所有Promise对象的成功结果。如果任何一个Promise对象失败,allPromise
将失败,并包含第一个失败的Promise对象的错误信息。
3. 使用场景
Promise.all
通常用于处理多个相关但相互独立的异步操作
,等待它们全部完成后再执行下一步操作。一个常见的应用场景是同时向多个API
端点请求数据,然后在所有数据都返回后进行处理。
javascript
const fetchData1 = fetch('https://api.example.com/data1');
const fetchData2 = fetch('https://api.example.com/data2');
const fetchData3 = fetch('https://api.example.com/data3');
const allDataPromise = Promise.all([fetchData1, fetchData2, fetchData3]);
allDataPromise
.then((responses) => {
return Promise.all(responses.map(response => response.json()));
})
.then((data) => {
console.log(data); // 所有API端点返回的数据数组
})
.catch((error) => {
console.error(error); // 如果任何一个API请求失败,输出错误信息
});
在这个例子中,allDataPromise
等待所有API
请求完成,然后将它们的响应用json
方法处理,最终输出一个包含所有API端点数据
的数组
。
总体而言,
Promise.all
是一个强大的工具,用于管理和协调多个异步操作,使得在它们全部完成后执行下一步操作变得更加简单。
Promise.race()
JavaScript中的Promise.race
方法是Promise
对象上的一个静态方法
,它提供了一种处理多个Promise
对象的方式,以便创建一个新的Promise
对象,其状态和结果取决于最先完成的原始Promise
对象。让我们深入了解这个有用的方法。
1. 语法和用法
Promise.race
方法的基本语法如下:
javascript
Promise.race(iterable);
iterable
: 一个可迭代对象,通常是包含Promise对象
的数组
。
Promise.race
返回一个新的Promise对象
,其状态和值将取决于第一个完成的原始Promise对象
。如果第一个Promise对象成功
,新Promise对象将成功
;如果第一个Promise对象失败
,新Promise对象将失败
。
2. 示例演示
让我们通过一个简单的例子来说明Promise.race
的用法:
javascript
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2 resolved');
}, 500);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Promise 3 rejected');
}, 800);
});
const racePromise = Promise.race([promise1, promise2, promise3]);
racePromise
.then((result) => {
console.log(result); // 第一个完成的Promise结果
})
.catch((error) => {
console.error(error); // 如果第一个完成的Promise失败,则输出错误信息
});
在这个例子中,racePromise
将与最先完成的promise1
或promise2
或promise3
具有相同的状态和结果。由于promise2
首先完成,racePromise
的状态将是Fulfilled
,并输出Promise 2 resolved
。如果promise3
首先完成,racePromise
将变为Rejected
,并输出Promise 3 rejected
。
3. 使用场景
Promise.race
常用于处理多个异步操作,但只关心最快完成的情况。例如,可以用它来设置一个超时机制,如果某个异步操作在一定时间内没有完成,就采取相应的措施。
javascript
const fetchData = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
resolve('Data fetched successfully');
}, 2000);
});
const timeoutPromise = new Promise((resolve, reject) => {
// 设置超时时间为1秒
setTimeout(() => {
reject('Timeout: Operation took too long');
}, 1000);
});
const resultPromise = Promise.race([fetchData, timeoutPromise]);
resultPromise
.then((result) => {
console.log(result); // Data fetched successfully
})
.catch((error) => {
console.error(error); // Timeout: Operation took too long
});
在这个例子中,resultPromise
将在fetchData
和timeoutPromise
中任何一个首先完成时完成。如果fetchData
在1秒内完成,它将成功并输出Data fetched successfully
,否则,timeoutPromise
将导致resultPromise
失败,并输出Timeout: Operation took too long
。
总体而言,
Promise.race
是处理异步操作的一种强大工具,特别适用于需要及时响应
的情况。
总结
Promise是JavaScript中处理异步操作的一种机制,它提供了更清晰、更结构化的方式来编写异步代码,避免了回调地狱的问题。以下是Promise处理异步的关键概括:
- 状态和状态转换: Promise有三个状态,分别是进行中(Pending)、已成功(Fulfilled)、已失败(Rejected)。一旦Promise状态从Pending变为Fulfilled或Rejected,就不会再改变。
- 创建Promise对象: 使用
new Promise()
构造函数创建一个Promise对象,该构造函数接受一个带有resolve
和reject
参数的函数,用于表示异步操作的成功和失败。- 处理Promise状态: 使用
.then()
处理成功的情况,使用.catch()
处理失败的情况。这些方法允许更清晰地定义在异步操作完成后要执行的代码。- Promise链: 使用
.then()
方法进行链式调用,允许按顺序执行多个异步操作,每个操作都依赖前一个操作的结果。- Promise.all方法:
Promise.all
方法用于将多个Promise对象合并成一个新的Promise对象。新的Promise对象的状态和值取决于所有原始Promise对象的状态,只有当所有原始Promise对象都成功时,新的Promise对象才会成功。- Promise.race方法:
Promise.race
方法用于将多个Promise对象合并成一个新的Promise对象,新的Promise对象的状态和值取决于最先完成的原始Promise对象。
如果这篇文章感觉对你有用的话,给作者一点鼓励点个赞吧♥
这个专栏在持续更新更多有用的干货中,关注➕收藏 Coding不迷茫
所有文章的源码,给作者的开源git仓库点个收藏吧: gitee.com/cheng-bingw...