首页 > 技术文章 > js基础--异步

cassie-coder 2018-08-24 13:31 原文

1.关于异步的几个概念

(1)触发和执行不是一个意思

计数器的回调函数一定会在指定的delay后触发,但此时不一定立即执行,可能需要等待(等待所需的资源的释放)

(2)事件队列

onclick等由浏览器的内核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)  
   })
}) 
console.log(data) //str
}

(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>标签的一个属性,规定脚本被异步执行

推荐阅读