开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,[点击查看活动详情]
你真的理的清Promise以及async、await语法糖的用处和使用场景吗?他们是三个不同的东西吗?之间是什么关系?看完这篇,相信你会对这三个好兄弟有更清晰的理解
三者的区别
传统的实现一个异步任务,我们通常使用回调函数的方式撰写,这样一来,我们无可避免的会使回调函数横向发展,也就是我们常说的callback hell,因此,我们可以引出Promise函数。
Promise
当遇到需要一个页面同时发送多个请求的情况时我们首先考虑的就是异步请求,在发送ajax请求的时候,总是会返回一个Promise对象异步函数的特点,返回值为promise 的函数;Promise确实是一个处理异步编程的解决方案,其本质其实是一个封装好的对象(所以要new)。我们在new一个Promise对象的时候,实际上promise会接受两个函数式参数(reject失败时回调、resolve成功时回调),因此我们在构造对象实际上是一个
let a=new Promise(function(,resolve,reject){ //里面进行一些异步请求 })
的过程。 而如果要深入了解promise的话实际上,promise执行的回调函数是基于一种状态机,通过判断不同的状态来实现不一样的函数。
promise的链式调用
promise内涵的.then方法可以有效地使异步函数随着 然后 的思路进行下去,使其执行成功或失败后的(.then方法都依赖上一步的结果。),可以将请求成功的参数通过.then(res)放进参数res里。链式调用相比传统的回调函数可以避免函数横向发展,提高代码的可读性。
在链式调用的过程中,如果我们希望捕获链式调用中有可能遇到的错误,可以参考try—catch—finally方法
async函数
主要作用:async函数其实就是起到一个标记的作用。
一个普通的function,在经过async function之后,会被标记为一个异步函数,而在被async标记的异步函数中,我们无需再调用.then方法,而是可以直接在内部使用await拿到promise函数返回之后的最终结果,如:
async function f(){ const response=await fetch("http:xxxxxx") }
我们拿到的response,就是该异步函数的最终返回值(一个promise对象)。
await函数
await作为一个配合async的方法,一般使用于被async标记的异步函数内,顾名思义,他通常起到一个阻塞的作用,其在使用的时候通常放置于一个Promise函数前,以此阻塞之后的异步操作进程;而他之所以放在promise函数前,原因很简单:他只能对promise起作用,而不能对回调函数起作用。
使用await时需要注意的一些陷阱
陷阱1
如果我们需要多次使用await函数的话,难免会打破他的并行原则(即等待前一个await执行完毕后再向后执行),其优化方式为,将多个promise使用promise.all的方式组合起来再await,如:
const [p,q]=await Promise.all([PromiseP,PromiseQ])
陷阱2
如果我们需要在循环中使用异步操作,我们也不可以使用例如map/forEach等方法,尽管我们写了await,他也会不听话不经过等待立即执行后面的代码;而是应该老老实实的写for循环~
总结
总而言之,由Promise衍生出来的async-await语法糖本质上就是基于promise的事件循环机制实现的,其最主要功能就是为了使代码看起来更简洁。