1. Promise
1. 出现原因
因为回调地狱,Promise实现了异步链式调用。
2. 优缺点
- 优点:
- 解决了回调地狱,实现了链式调用
- 缺点:
- catch只能捕获到reject()抛出的错误
- 未完成一直处于pending状态,无法中途取消,无法确定执行到哪一步
3. 注意事项
4. 使用
Promise返回的还是Promise对象,可以一直(.then())链式调用下去。 Promise三种状态:pending、fulfilled、rejected
function queryData(url) {
// 里面逻辑决定是执行resolve还是reject。
//resolve或reject会把这个异步返回值暂存下来,等着then去接收
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
// 处理正常的情况
resolve(xhr.responseText);
} else {
// 处理异常情况
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
queryData('https://www.baidu.com/')
.then(function (data) {
console.log(data) //如果promise返回的是resolve状态,这里就打印xhr.responseText
})
.catch(function (data) {
console.log(data) //如果promise返回的是reject状态,这里就打印‘服务器错误’
})
.finally(function () {
console.log('finished') // 成功失败最后都会执行
});
Promise内置方法:**
- p.then() 得到异步任务的正确结果
- p.catch() 获取异常信息
- p.finally() 成功与否都会执行(尚且不是正式标准)
- Promise.all() 所有任务都执行完成才能得到结果
- Promise.race() 只要有一个任务完成就能得到结果 ```javascript // queryData:封装的请求函数,返回Promise对象 var p1 = queryData(‘http://localhost:3000/a1‘); var p2 = queryData(‘http://localhost:3000/a2‘); var p3 = queryData(‘http://localhost:3000/a3‘); Promise.all([p1,p2,p3]).then((result) => { // all 中的参数 [p1,p2,p3] 和 返回的结果一 一对应[“HELLO TOM”, “HELLO JERRY”, “HELLO SPIKE”] console.log(result) //[“HELLO TOM”, “HELLO JERRY”, “HELLO SPIKE”] })
Promise.race([p1,p2,p3]).then((result) => { // 由于p1执行较快,Promise的then()将获得结果’P1’。p2,p3仍在继续执行,但执行结果将被丢弃。 console.log(result) // “HELLO TOM” })
<a name="WY4Vi"></a>
### 2. async/await
<a name="XpDUi"></a>
#### 1. 出现原因
> Promise的then链问题,await 实现了异步代码同步写
<a name="l06dw"></a>
#### 2. 优缺点
- **优点**
- 使用try...catch可以捕获代码运行的所有错误,不仅仅是catch抛出的错误
- **缺点**
- 会阻塞代码,Promise不会
<a name="AkUo6"></a>
#### 3. 注意事项
1. await只能在带有async修饰的函数中使用
1. async函数返回值是Promise对象
1. await右侧表达式如果是Promise对象,await返回的是Promise成功的值;await右侧是普通表达式,相当于同步代码。
1. 不要滥用await,阻塞代码,可能会使性能降低
<a name="laVhF"></a>
#### 4. 使用
1. **基本使用**
```javascript
async function test(){
try{
// queryData为上面封装的请求方法
let res1 = await queryData("https://www.baidu.com/1")
let res2 = await queryData("https://www.baidu.com/2")
}catch(error){
console.log(error)
}
}
- 循环中调用异步
async function demo(arr) {
for await (let i of arr) {
handleDo(i);
}
}