原文git
以前总结了关于 JavaScript 异步的 事件循环与消息队列 机制以及 ES6 带来的 微任务与宏任务 的知识。传送门github
下面是关于JS异步处理的各类方案:ajax
callback >> ES6 Primise >> async/await
复制代码
先看一段代码:bash
// 假设有一个耗时的异步请求 ajax,在 2 秒后打印日志
function ajax () {
// do something...
setTimeout(() => {
console.log('Hello, Zavier Tang!')
}, 2000)
}
ajax()
// do something...
console.log('The end.')
// The end.
// Hello, Zavier Tang!
复制代码
这里模拟了一个简单的异步网络请求,并在 2 秒后打印 "Hello, Zavier Tang!",而后作一些处理("do something")后,打印结束 "The end."。网络
结果是先打印的 "The end."。异步
显然这并非咱们要的结果,"异步请求" ajax
中的 setTimeout
并无阻塞代码的执行,而是直接执行了 console.log()
。async
一样是上面的异步网络请求,这里使用 callback 回调函数的方式解决 JavaScript 同步带来的问题。函数
function ajax (fn) {
// do something...
setTimeout(() => {
console.log('Hello, Zavier Tang!')
fn()
}, 2000)
}
ajax(() => {
// do something...
console.log('The end.')
})
// Hello, Zavier Tang!
// The end.
复制代码
这里咱们直接把异步请求以后要作的一些操做作为回调函数,传递到 ajax 中去,并在异步请求结束后执行回调函数里的操做。post
问题彷佛已经解决了??可是,若是有多个异步请求,而且在每一个异步请求完成后都执行一些操做,那代码就会像下面这样:学习
function ajax (fn) {
// do something...
setTimeout(() => {
console.log('Hello, Zavier Tang!')
fn()
}, 500)
}
ajax(() => {
// do something...
console.log('The end 1.')
ajax(() => {
// do something...
console.log('The end 2.')
ajax(() => {
// do something...
console.log('The end 3.')
ajax(() => {
// do something...
console.log('The end 4.')
ajax(() => {
// do something...
console.log('The end 5.')
// ......
// ......
})
})
})
})
})
// Hello, Zavier Tang!
// The end 1.
// Hello, Zavier Tang!
// The end 2.
// Hello, Zavier Tang!
// The end 3.
// Hello, Zavier Tang!
// The end 4.
// Hello, Zavier Tang!
// The end 5.
复制代码
看起来很吓人!!
若是是这样:请求1结束后进行请求2,而后还有请求三、请求四、请求5,而且请求2还可能依赖于请求1的数据,请求3依赖于请求2的数据,不停的一层一层嵌套,对于错误的处理也极不方便,因此称之为 callback 回调地狱。
ES6 的 Promise 被称为 JS 异步的下一代解决方案。
关于 Promise:
接下来使用 Promise 处理异步:
function ajax (word) {
return new Promise((resolve) => {
// do something...
setTimeout(() => {
resolve('Hello ' + word)
}, 500)
})
}
ajax('请求1')
.then((word) => {
console.log(word)
console.log('The end 1.')
return ajax('请求2')
})
.then((word) => {
console.log(word)
console.log('The end 2.')
return ajax('请求3')
})
.then((word) => {
console.log(word)
console.log('The end 3.')
})
// .catch(() => {})
// Hello 请求1
// The end 1.
// Hello 请求2
// The end 2.
// Hello 请求3
// The end 3.
复制代码
上面仍是连续的异步请求,每次请求后打印日志。这样看起来比上面的回调地狱舒服多了,每一个请求经过链式的调用,在最后能够对全部的请求进行错误处理。
但,彷佛还并非特别优雅。
关于 async/await 的简介:
体验一下神奇的 async/await:
// 接上面的代码
async function doAsync () {
const word1 = await ajax('请求1')
console.log(word1)
console.log('The end 1')
const word2 = await ajax('请求2')
console.log(word2)
console.log('The end 2')
const word3 = await ajax('请求3')
console.log(word3)
console.log('The end 3')
}
doAsync()
// Hello 请求1
// The end 1
// Hello 请求2
// The end 2
// Hello 请求3
// The end 3
复制代码
这样看起来,更优雅了。没有任何括号,也没有 callback,没有 then,直接申明 async,使用 await 等待异步执行完成,看起来也更像是同步的代码。
JavaScript 的异步编写方式,从 callback 回调函数到 Promise ,再到 async/await,只能说。。。
技术发展太快啦,赶忙学习吧!