Promise的作用
Promise是一个对象,代表一个异步操作是成功还是失败。Promise的作用:
1、同时处理多个并发请求操作。
2、链式调用用来解决回调地狱问题。
(注:回调地狱,即回调函数中调用的函数依赖回调函数运行的结果,多个这样的回调函数构成回调地狱。)
Promise的使用
Promise的约定:
- 在本轮事件循环运行完成之前,回调函数不会执行。
- 通过then()添加的回调函数一定会被执行。
- 通过多次调用then(),可以添加多个回调函数。
Promise的用法:
一般链式写法
new Promise((resovle, reject)=>{
resovle()
}).then((resovle, reject) => {
resovle() // reject()
})
.then((newResult)=> {
return doThirdThing(newResult); //返回结果
})
.then((finalResult)=> {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
组合用法
同时执行多个异步:Promise.all([])、Promise.race([])
Promise.all([]):最慢的异步操作执行完,再去调用回调。
Promise.race([]):最快的异步操作执行完,就去调用回调。
手动创建一个成功或失败的Promise: Promise.resolve()/Promise.reject()
Promise中的错误处理
catch捕获错误,只捕获当前链上的错误,不包含嵌套promise链上的错误。
例子1:
new Promise((resolve, reject) => {
console.log('初始化');
resolve();
})
.then(() => {
throw new Error('有哪里不对了');
console.log('执行「这个」”');
})
.catch(() => {
console.log('执行「那个」');
})
.then(() => {
console.log('执行「这个」,无论前面发生了什么');
});
//初始化
//有哪里不对了
//执行「那个」
//执行「这个」,无论前面发生了什么
例子2: 包含一个嵌套promise链,就算这个嵌套链上没有catch,这个嵌套链上的报的错,最外面的promise链上的catch也不能捕获到。
new Promise((resolve, reject) => {
console.log('初始化');
resolve();
})
.then(() => {
new Promise((resolve, reject) => {
console.log('「嵌套」');
resolve();
}).then(()=> {
throw new Error('有哪里不对了');
}).catch(()=> {
console.log('执行「嵌套」');
})
console.log('执行「这个」');
})
.catch(() => {
console.log('执行「那个」');
})
.then(() => {
console.log('执行「这个」,无论前面发生了什么');
});
//初始化
//「嵌套」
//有哪里不对了
//执行「这个」
//执行「这个」,无论前面发生了什么
注意点:
- then() 返回一个promise对象
- then()中的参数可选,catch(failureCallback)等同于then(null, failureCallback)
- then()中return返回Promise链
- 最后通过catch终止Promise链
- catch只捕获当前链上的错误,不包括其嵌套promise链上的错误
Promise的应用场景举例
合适的使用Promise可以编写更具可复用性和可维护性的代码。
案例1:
封装一个等待1000毫米的函数
function sleep(time) {
return new Promise((r, j) => {
setTimeout(() => {
r()
}, time);
})
}
sleep(1000).then(success => {
console.log('success')
}).catch(err => {
})
最常见的应用场景是封装一个ajax请求
// 简略实现ajax
function ajax(url,type){
return new Promise((resolve,reject) => {
var XHR = new XHRHttpRequest();
XHR.open(type,url,true);
XHR.send();
XHR.onreadystatechange = () => {
if(XHR.readyState == 4) {
if(XHR.status == 200) {
try {
let response = JSON.parse(XHR.responseText);
resolve(response);
} catch(e) {
reject(e);
}
} else {
reject(new Error(XHR.statusText));
}
}
}
});
}
案例2:
图片请求超时提醒
function requestImg(){
var p = new Promise((resolve, reject) => {
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = '图片的路径';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise.race([requestImg(), timeout()]).then((data) =>{
console.log(data);
}).catch((err) => {
console.log(err);
});
参考资料: