上一篇基于JavaScript基础的异步、同步操作,promise、.then()-CSDN博客讲了【啥是异步操作、同步操作?】然后简单讲了回调函数是啥、Promise()对象是啥、.then()函数是啥,这一篇讲讲promise()对象到底怎么配合.then()函数解决回调地狱,还有Async、Await又是啥。
一、最简单的方式了解怎么用【Promise对象配合.then()】解决回调地狱
1、首先回顾一下Promise对象配合.then()的用法,一张图看明白
2、接下来,我们找个回调地狱的例子:
假设我要依次隔1秒输出【广东省】->【阳江市】->【阳东区】->【东城镇】
先按蠢方法
这样写看得人眼睛都花了,这啥啊?老方法的.then()就是不断创建新的Promise对象,然后把resoleve()成功函数里把上一个【成功的结果】拼上【新的成功结果】传出去,传到下一个.then()函数里,依次反复,估计我讲这么多没人会看,也没人看懂,那么我们跳过
3、现在我们优化一下,怎么搞?简单理解:
1、.then()函数是怎么获取到resolve()成功函数的结果的?只要Promise对象设置了resolve()成功函数,然后Promise对象自己调用自己的.then()回调函数,这个回调函数的参数自动就接收【resolve()成功函数】的传出去的参数结果
2、那么第一步必须得有一个Promise对象,里面照上面操作设置resolve、reject函数并往里传入像输出的结果作为参数,然后在外面用Promise对象.then()输出结果
const p = new Promise(( resolve, reject ) => {resolve('成功的结果')reject(new Error('错的提示'))
})p.then(res=>{//拿到第一个‘成功的结果’
})
3、第三步重要了!!很简单,你在这个.then()函数里return一下结果,这个结果不就可以传出去给别人用了吗?然后在这个.then()后面再接一个.then()函数,刚刚return的结果就给到下一个.then()函数了,它再拿到上一个的结果,跟上自己的结果return给下一个,下下个.then()又接到它return的
p.then(res=>{return 结果
}).then(res=>{return 结果
}).then(res=>{return 结果
})
......
4、然后注意一点,我们不是简单return个【结果】就行了,你要一直用.then()函数的话,要想一想.then()是谁的函数?要Promise对象才可以调用.then()啊,而且.then()接收的结果也是来自Promise对象的resolve成功函数传出的结果,总而言之!你return的东西应该是一个【Promise对象】!!!!
你把【包含了要输出的结果】的【Promise对象】return出去,然后这个【Promise对象】调用.then(),再接着把【包含了要输出的结果】的【Promise对象】return出去
最后优化结果是这样:
代码在这:
const p = new Promise(( resolve, reject ) => {setTimeout(()=>{resolve('广东省')reject(new Error('错了'))},1000)
})p.then(res=>{return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve(res + '阳江市')reject(new Error('错了'))},1000)})
}).then(res=>{return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve(res + '阳东区')reject(new Error('错了'))},1000)})
}).then(res=>{return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve(res + '东城镇')reject(new Error('错了'))},1000)})
}).then(res=>{console.log(res)
})
二、如果上面的你理解起来还是很头晕,那么现在来了解【Async】、【Await】是什么
上面的例子还是要一会又return,一会又.then(),哪个结果对应到哪个.then()函数,一时还真不好找,那么现在有这两个东西修改一下写法:【Async】、【Await】
【Async】:不用去查那么复杂的解释,简单理解就是【异步函数】,任何函数前面加了Async关键字,那就是一个【Async异步函数】
【Await】:Await函数就是等待一个Promise对象兑现成功或失败后,把resolve或reject的结果值返回给Await,说白了他就是.then()的替身,它来获取Promise对象的结果。用它的条件:1、必须有Promise实例 2、必须在【异步函数里】,也就是只能在【Async函数】里用
总结:它两配合起来就可以写出看着像【同步操作】写法的【异步操作】,会舒服一点
那怎么用?
1、第一步,把你要有先后次序的这些事情分别写在不同的函数里,然后这些函数要这些事情、结果输出,就要return一个包含这些结果的Promise对象,这样await就可以调用并获得这些函数结果
function A(){return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve('广东省')reject(new Error('错了'))},1000)})
}
function B(){return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve('阳江市')reject(new Error('错了'))},1000)})
}
function C(){return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve('阳东区')reject(new Error('错了'))},1000)})
}
function D(){return new Promise(( resolve, reject ) => {setTimeout(()=>{resolve('东城镇')reject(new Error('错了'))},1000)})
}
2、第二步,因为await函数需要在【异步函数】里,那么async就是异步函数,那就是用async声明的一个函数包住await函数就行了,最后别忘了调用执行这个async函数
async function fn(){const res = await A()console.log(res)const resB = await B()console.log(resB)const resC = await C()console.log(resC)const resD = await D()console.log(resD)
}//最后别忘了调用执行这个async函数,上面只是声明函数
fn()
现在你看,是不是能很清晰的看出哪个结果来自哪个函数了
三、这两玩意广泛用于获取axios网络请求返回的结果
axios和Promise
学过ajax的知道axios库是一个发送网络请求的HTTP客户端,它的底层原理就是基于在一个【Promise对象】里创建一个【XMLHttpRequest对象】,然后把传给axios库的服务器网址参数传给自己函数里的【Promise对象】的【XMLHttpRequest对象】,进行发送请求,然后把请求成功的结果或失败的结果,通过【Promise对象】return出去
这里给大伙看一个自己手动创建一个本地axios库的例子方便大家理解
function MyAxios(config){return new Promise(( resolve , reject ) => {//创建XMLHttpRequest()对象来发送请求const xhr = new XMLHttpRequest()//这里直接用对象的属性来open(), “对象形参.method”如果没有设置就是undefined,那么就自动选'请求方式',然后url也用下面调用时传的对象参数的属性就行xhr.open(config.method || 'get' , config.url)xhr.addEventListener('loadend',function(){//通过状态码来判断是成功还剩失败,状态码一般200多的就是成功,所以只要>=200 && < 300就行if(xhr.status >= 200 && xhr.status < 300){resolve(JSON.parse(xhr.response))//请求成功结果}else{reject(new Error(xhr.response))//请求失败结果}})xhr.send()})
}MyAxios({url: 'https://hmajax.itheima.net/api/province',
}).then(res => {console.log(res)
}).catch(err => {document.querySelector('.myP').innerHTML = err.message
})
所以我们学axios库的时候,才会用axios()库去调用.then()、.catch()函数,因为axios库函数它return的就是【Promise对象】,也就是一个【Promise对象】在用.then()、.catch()方法。
既然如此,那么用【async】和【await】也同样可以
现在我们知道axios就是基于Promise对象的,那么当使用axios发送请求时,就会返回一个Promise对象,然后【await函数】就可以等待Promise对象兑现结果之后,获取到它的成功或失败的结果,然后在搭配async函数,完美,这样就可以获得axios库返回的结果了,不用.then()和.catch()了
async function fn(value){//设一个变量接收await获取到的axios返回的网络请求结果const res = await axios({url: 'https://applet-base-api-t.itheima.net/api/translate',params: {words: value}})console.log(res)
}fn('damn')
讲完了,要是还看不懂,那你就转行吧,没希望了兄弟