感性上的理解:Promise
咱们能够理解为作了一个保证,作了这个保证无论成功resolve()
仍是失败reject()
都会告知咱们———返回带有最终结果或者拒绝缘由 的Promise
。javascript
其中后两种都是异步操做完成后的状态java
Promise
对象用于表示一个异步操做的最终状态(完成或失败),以及其返回的值。ios
MDN对Promise的定义如上,能够理解为此对象作了一些保证,告知咱们异步操做的状态。具体以下:axios
存在的需求:有时候咱们须要连续调用多个异步操做,每个操做都创建在获得上一部结果以后。之前有回调函数,这样会容易形成回调地狱。而采用Promise以后,每一步操做成功/失败以后都会带上其结果,执行下一个操做。api
// 回调地狱
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
//采用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);
复制代码
在上面的代码段1中,有三个错误回调函数。而在Promise链式调用中,只在结尾加上错误处理回调便可,当有错误抛出时,会返回一个带有错误缘由的Promise到下一级catch,直到最底端catch函数。数组
// 依次输出: Initial Do that
new Promise((resolve, reject) => {
console.log('Initial');
resolve();
})
.then(() => {
throw new Error('Something failed');
console.log('Do this');
})
.then(() => {
console.log('Do this whatever happened before');
})
.catch(() => {
console.log('Do that');
})
复制代码
此外,若是中途捕获了异常,依然能够接着then下去:promise
/* * 依次输出: * Initial * Do that * Do this whatever happened before */
new Promise((resolve, reject) => {
console.log('Initial');
resolve();
})
.then(() => {
throw new Error('Something failed');
console.log('Do this');
})
.catch(() => {
console.log('Do that');
})
.then(() => {
console.log('Do this whatever happened before');
})
复制代码
缘由在于catch(failureCallback)
自己是then(null, failureCallback)
的缩略形式,也是返回带有当前状态的Promise。下面这样我们还能捕获到异常信息:app
/* * 依次输出: * Initial * Something failed * Do that * Do this whatever happened before */
new Promise((resolve, reject) => {
console.log('Initial');
resolve();
})
.then(() => {
throw new Error('Something failed');
console.log('Do this');
})
.catch((e) => {
console.log(e.message)
console.log('Do that');
})
.then(() => {
console.log('Do this whatever happened before');
})
复制代码
一个栗子异步
// 使用Promise
doSth()
.then(res => doSthElse(res))
.then(newRes => doThirdTh(newRes))
.then(finalRes => {
console.log(`finalResult is ${finalRes}`)
})
// 使用async/await将异步代码写成同步样式
async funtion foo () {
let res = await doSth()
let newRes = await doSthElse(res)
let finalRes = await doThirdTh(newRes)
console.log(`finalResult is ${finalRes}`)
}
复制代码
使用这两种静态方法能够建立resolve或reject的保证,栗子以下:async
getRecommend () {
let today = new Date()
let date = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate(), 9)
return axios.get(`/api/getRecommend?date=${Number(date)}`
).then(response => {
return Promise.resolve(response.data)
}).catch(err => {
console.log(err)
})
}
复制代码
当使用axios
成功请求/api/getRecommend
时,axios返回一个Promise对象,由于getRecommend()
是要export出去的,这里直接返回一个状态完成的Promise,调用getRecommend()
时,若是成功响应直接能够recommend.getRecommend().then(res => {})
获取响应结果。
Promise.all()
是全部Promise对象状态都是‘已成功’才结束Promise.race()
是有一个Promise对象状态‘已成功’就结束下面这个累加例子很好地显示了Promise之间传值计算:
// 第一步,执行XXX操做,保证了***结果
let step1 = function () {
let val = 1
console.log(`this is step1 , the value is ${val}`)
// 拒绝的状况,balalala...
if (val > 0){
return Promise.resolve(val)
}
return Promise.reject(val)
}
// 第二步,执行XXX操做,保证了***结果
let step2 = function (val) {
val += 1
console.log(`this is step2 , the value is ${val}`)
return Promise.resolve(val)
}
// 第三步,执行XXX操做,保证了***结果
let step3 = function (val) {
val += 1
console.log(`this is step3 , the value is ${val}`)
return Promise.resolve(val)
}
step1().then((val)=>{
return step2(val)
}).then((val)=>{
return step3(val)
}).then((val)=>{
console.log(`finally, the value is ${val}`)
})
// 输出结果
this is step1 , the value is 1
this is step2 , the value is 2
this is step3 , the value is 3
复制代码
再用async/await
语法糖实现一遍累加
// 在这里咱们把每一步操做看做异步的
function step21() {
let val = 1
console.log(`this is step1 , the value is ${val}`)
return val
}
function step22(val) {
val += 1
console.log(`this is step2 , the value is ${val}`)
return val
}
function step23(val) {
val += 1
console.log(`this is step3 , the value is ${val}`)
return val
}
(async () => {
// await使用必须在async函数内
let val = await step21()
val = await step22(val)
val = await step23(val)
})()
// 输出结果
this is step1 , the value is 1
this is step2 , the value is 2
this is step3 , the value is 3
复制代码
使用数组的reduce()
方法依次执行,
// 第一步,执行XXX操做,保证了***结果
let step1 = function () {
let val = 1
console.log(`this is step1 , the value is ${val}`)
// 拒绝的状况,balalala...
if (val > 0){
return Promise.resolve(val)
}
return Promise.reject(val)
}
// 第二步,执行XXX操做,保证了***结果
let step2 = function (val) {
val += 1
console.log(`this is step2 , the value is ${val}`)
return Promise.resolve(val)
}
// 第三步,执行XXX操做,保证了***结果
let step3 = function (val) {
val += 1
console.log(`this is step3 , the value is ${val}`)
return Promise.resolve(val)
}
let steps = [step1, step2, step3]
steps.reduce((promise, fn, index)=>{
console.log(index)
return promise.then((val)=>{
return fn(val)
})
// reduce函数init参数
}, Promise.resolve())
// 输出结果
this is step1 , the value is 1
this is step2 , the value is 2
this is step3 , the value is 3
复制代码
暂时只想到数组的方法,使用Array.prptotype.reduce()
为解决,仍是没有深刻了解reduce()
是如何实现的
async function foo () {
let val
for (let i = 0; i < steps.length; i++) {
if (i===0) {
val = await steps[i]()
}else {
val = await steps[i](val)
}
}
}
foo()
复制代码