为什么使用Promise
前端开发中经常会接触到异步操作的处理,以往是在异步回调函数中继续处理业务逻辑,如果此时的业务中又出现了一个甚至多个异步操作,那么就会造成以下局面,也就是所谓的回调地狱。
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
而使用了Promise后可以避免层层调用的情况,变为链式调用,形成一个 Promise 链:
doSomething().then(function(result) {
return doSomethingElse(result);
}).then(function(newResult) {
return doThirdThing(newResult);
}).then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
}).catch(failureCallback);
Promise简介
1、Promise的状态和状态改变
1.1、Promise的状态
- pending(待定):初始状态,既没有被兑现,也没有被拒绝。
- fulfilled(已兑现):意味着操作成功完成。
- rejected(已拒绝):意味着操作失败。
1.2、状态变化
Promise的初始状态是pending,初始状态下的Promise 对象要么会通过一个值被兑现,要么会通过一个原因(错误)被拒绝。当这些情况之一发生时,我们用 promise 的 then或catch 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序也同样会被调用,因此在完成异步操作和绑定处理方法之间不存在竞态条件。
2、Promise的链式调用
.then() 函数可以接受两个参数,第一个参数作为处理已兑现状态的回调函数,而第二个参数则作为处理已拒绝状态的回调函数。每一个 .then() 方法还会返回一个新生成的 promise 对象
因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回的是 promise,所以它们可以被链式调用。
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('foo');
}, 300);
});
myPromise
.then(handleResolvedA, handleRejectedA)
.then(handleResolvedB, handleRejectedB)
.then(handleResolvedC, handleRejectedC);
示例(Promise封装Ajax)
function promiseAjax(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState!==4) return
const {status, response} = xhr
// 请求成功, 调用 resolve(value)
if (status>=200 && status<300) {
resolve(JSON.parse(response))
} else { // 请求失败, 调用 reject(reason)
reject(new Error('请求失败: status: ' + status))
}
}
xhr.open("GET", url)
xhr.send()
})
}
promiseAjax('XXX')
.then(data => {
console.log('显示成功数据', data)
},error => {
alert(error.message)
})