在Javascript中函数是第一类对象,可被存储在变量中,也能作为函数的参数传递
js是单线程语言,所有脚本同步执行,但是我们有时候需要等待某个时机才执行某些脚本也就是做异步操作,于是出现了如下代码:
我们成setTimeout函数中的参数为回调函数
当我们需要在2000ms后,再开启一个定时器,则会如下定义代码:
如果需要再timer end2输出后开启更多的定时器,则需要依次嵌套下去,如此变出现了一列回调小火箭,我们称之为回调地狱
这段代码虽然在功能上不存在什么问题,但是在代码可读性以及维护性方面惨不忍睹,对此es6提供了一些列异步编程解决方案。
1、promise
prmoise是一个对象,专门用于处理异步操作,该对象有三个状态:进行中、已完成、已失败,当前状态仅由异步操作的结果决定,不受任何其他操作控制,且一旦执行就无法取消
上图代码,resolve函数执行后,promise对象状态将会从“未完成”变为“成功”,reject则是变为“失败”,基于此我们可以使用then方法分别指定“成功”与“失败”状态的回调函数
如此可便可以通过链式调用的方式将执行逻辑串联起来,同时也将回调处理从上层代码中抽离
2、async
promise对象的链式串联方式虽然解决了回调函数的层层嵌套问题,但是then操作过多过长时还是会出现冗余臃肿的情况,此时可以使用async函数。
async函数是es7的语法,但是bable已经提供了相关的转译功能
function timeout(data){
return new Promise((resolve, reject)=>{
setTimeout(function(){
if(data){
resolve(data)
}else{
reject(data)
}
},3000)
})
}
class agent{
async run(){
console.log("agent run start")
await timeout("agent")
console.log("agent run end")
}
}
let agentIns = new agentExtend();
agentIns.run()
如上图所示,还是使用了前面的timeout函数,只不过在run方法上加了async标识,然后在调用异步promise函数时加上await关键字,console.log("agent run end")函数则会等待timeout函数执行resolve()操作后再执行,如果由多个异步操作,则在每个异步函数前加上await关键字即可达到暂缓执行的效果,直到异步Promise对象状态改变
最后说明一下,promise,async都是外同内异,看起来是同步执行的效果,本质上还是异步回调,只不过ECMAScript包装过的一个语法糖