async 与 await 是ES8 中提出的语法,主要是为了解决异步任务的回调。
这里总结了几种处理异步任务回调的方法,从中观察async是如何诞生的。
这里利用node环境下的文件读写举例。
普通回调
fs.readFile('./app.js', (err, data) => {
console.log(data.toString())
})
封装Promise
function readFile(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
if (err) {
reject(err)
return;
}
resolve(data)
})
})
}
readFile('./app.js')
.then(res => {
console.log(res.toString())
})
.catch(err => {
console.log(err)
})
node 工具 Promisify
与封装Promise差不多,只是封装这一步,node替你做了而已。
const promisify = require('util').promisify
const readFile = promisify(fs.readFile)
readFile('./app.js')
.then(res => {
console.log(res.toString())
})
.catch(err => {
console.log(err)
})
Generator
yield
会给函数的执行添加一个“断点”,只有调用next()
才能继续运行。
function* fn() {
yield console.log(1)
yield console.log(2)
console.log(3)
}
const fn1 = fn()
fn1.next()
fn1.next()
fn1.next()
async & await
其实和Promise,Generator都有很大的联系,这里利用一个node做一个接口,然后看一下如何利用async和await处理axios请求。
- node
const express = require('express')
const app = express()
app.use(require('cors')())
app.get('/', (req, res) => {
res.json({
status: 200,
message: 'ok'
})
})
app.listen(3000, () => {
console.log("Running")
})
- axios
(async function () {
const res = await axios.get('http://127.0.0.1:3000')
console.log(res.data)
})()
- 结果
{
"status": 200,
"message": "ok"
}
在我的理解中,async中的await会把函数执行停在此处,只有在异步任务完成之后,才会继续进行。
当然不是真正的停止,不然js也太笨了,只是说表现。
想要验证这个表现很简单,把 await 去掉,输出的结果就变为undefined
。因为console.log()
是同步任务,但是axios.get()
为异步任务,根据js的执行机制,肯定会先输出。输出的数据还没有请求过来呢,当然就是undefined
了。