异步的实现原理
例如AJAX,不会立即执行,而是等待请求成功之后才能执行
传递过去不执行,等待结果后再执行的函数,称之为回调函数
实现异步的核心原理:将callback作为参数传递给异步执行函数,当有结果返回之后再触发callback
常见的异步操作:
网络请求
IO操作
定时函数:setTimeout只在指定时间后执行一次
setInterval以指定时间为周期循环执行
异步操作不进入主线程,而是进入“任务队列”
异步执行机制:·分为执行栈和任务队列两步
●主线程空,就会去读取“任务队列”
●异步必须指定回调函数,主线程执行异步任务,就是执行对应的回调函数
异步和event-loop(轮询机制):主线程丛“任务队列”中读取事件
Node.js的event-loop:不同于浏览器环境
process.nextTick:它指定的任务总是发生在所有异步任务之前
setImmediate:在当前“任务队列”的底部添加事件,它指定的任务总是在下一次
event loop执行(setImmediate指定的回调函数,总是排在setTimeout前面,实际上,这种情况只发生递归调用的时候)
事件绑定算不算异步?
看起来一样
同:同样使用event-loop,
异:事件绑定有明显的订阅-发布模式
异步操作完成后,系统会自动调用;事件绑定之后,需要用户手动调用
异步调用方式
- 回调函数callback
fn2(fn3):fn2和fn3完全耦合在一起,保证fn3是在fn2之后执行的 事件订阅/发布(ES5)
如何顺序执行?(保证const asyncFunArr = new AsyncFunArr(fn1, fn2, fn3)中fn函数是顺序执行的)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class AsyncFunArr {
constructor (...arr) {
this.funcArr = [...arr]
}
next() {
const fn = this.funcArr.shift()
if (typeof fn === 'function') fn()
}
run () {
this.next()
}
}
const asyncFunArr = new AsyncFunArr(fn1,fn2,fn3)
function fn1 (){
console.log("Funtion1")
asyncFunArr.next()
}
function fn2 (){
setTimeout(() => {
console.log('Function2')
asyncFunArr.next()
},500)
}
function fn3 () {
console.log('Function 3')
asyncFunArr.next()
}Promise:函数返回Promise
1
2
3
4
5
6
7
8function fn2 () {
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('Function 2')
resolve()
},500)
})
}generator:异步函数会通过yield执行,异步函数内通过next激活generator函数的下一步操作(维护内部yield的执行)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function fn2 () {
setTimeout(() => {
console.log('Function 2')
af.next()
},500)
}
function* asyncFunArr (...fn) {
fn[0]()
yield fn[1]()
fn[2]()
}
const af = asyncFunArr(fn1,fn2,fn3)
af.next()使用async/await——————Promise-async/await
1
2
3
4
5
6
7
8
9
10
11
12
13
14function fn2 () {
return new Promise((resolve,reject)=> {
setTimeout(() => {
console.log('Function 2')
resolve()
},500)
})
}
async function asyncFunArr(){
fn1()
await fn2()
fn3()
}
asyncFunArr()