1.关于异步的几个概念
(1)触发和执行不是一个意思
计数器的回调函数一定会在指定的delay后触发,但此时不一定立即执行,可能需要等待(等待所需的资源的释放)
(2)事件队列
等由浏览器的内核DOM binding模块处理,当事件触发时,立即加入任务队列
setTimeout由timer模块进行延时处理,当时间到达时,它的回调才被加入任务队列
ajax由network模块处理,当网络请问完成时,回调才被加入任务队列
(3)setTimeout,setInterval
setTimeout是delay一定时间后将回调加入任务队列,而setInterval是每个一定时间后将回调加入任务队列,但是如果此时任务队列里还有此回调,则会忽略此次,所以setInterval可能会出现中间某次没有执行的情况
(4)事件循环
js会创建一个类似while的循环,每次tick查看是否有待处理的事件,如果有就取出并放入主线程执行
(5)在es6,新增的任务队列,如(promise)优先级比任务队列优先级更高
2.promise
以前对于异步处理,我们都是通过回调来处理,将回调拆解成一个个的function,或者使用事件发布/监听模式等多种方式来处理较复杂的异步,
现在es6给出了新的解决方案,promise,对于不支持promise的IE11和Opera Mini,我们使用polyfill可处理,es6-promise
(1) promise内部实现了resolve和reject这两个回调,通过它们可修改promise对象的状态,将异步操作的结果通过参数传递出去
new Promise((resolve,reject) => { asyncfun() resolve( 'end' ) }).then(data => { console.log(data) //end }) |
(2) 经常使用到的Promise.all()接收promise数组,按顺序添加进入异步队列,等所有任务结束后,结果按顺序映射到result内,返回的仍是一个数组
Promise.all([promise1,promise2,promise3]).then(result => { console.log(result) //[] }) |
3.async await
promise解决了我们对于异步的很多麻烦,但是仍显冗余,需要.then()同时里面使用匿名函数接收结果,所有在promise基础上有了async函数,这是es2017的标准
(1)async用于声明一个函数的异步函数,它总是返回promises,无论这个函数内部return什么值
const asyncFun1 = async () => { return 'str' } const asyncFun2 = async () => { return new Promise((resolve,reject) => { setTimeOut(() => { resolve( 'str' ) },1000) }) } |
asyncFun1内部return一个字符串,实际上会被包装成Promise.resolve('str'),asyncFun2本身就返回以一个promise对象
(2)await 操作符用于等待promise或其他要等待的值,只能在async函数内使用
async () =>{ let data = await new Promise((resolve,reject) => { |
setTimeOut(() => { resolve( 'str' ) },1000) }) |
1 | }) <br>console.log(data) //str<br>} |
(3)多个异步处理,
串行处理(等待前一个异步执行完后,发起后一个异步)
并行处理(多个异步同时发起,等待异步完成)
const seriaFn = async () => { console.time('seriaFn') console.log(await asyncFunction('str1')) console.log(await asyncFunction('str2')) console.timeEnd('seriaFn') //串行处理,耗时约2000ms /*等价于 asyncFunction('str1').then(str => { console.log(str) return asyncFunction('str2') }).then(str => { console.log(str) })*/} const parallel = async () => { console.time('parallel') const parallelOne = asyncFunction('str1') const parallelTwo = asyncFunction('str2') console.log(await parallelOne) console.log(await parallelTwo) //耗时约1000毫秒/*等价于 const [parallelOne,parallelTwo] = await Promise.all([asyncFunction('str1'),asyncFunction('str2')]) *//*或者 Promise.all([asyncFunction(),asyncFunction()]).then([result1,result2] => { console.log(result1,result2) })*/}
4.async模块
这是一个很实用的模块,提供了强大的函数来支持异步处理,包括async.map()等20多个功能性的方法,和async.waterfall()等异步控制的方法,具体可查看api
5.async也是html5<script>标签的一个属性,规定脚本被异步执行
原文出处:https://www.cnblogs.com/cassie-coder/p/9529331.html