async/await
是 ES7
中用来处理异步回调的一种写法,我们知道以前处理异步回调传统写法都是 callback
和promise
这两种,那么我们可以先来回忆一下 callback
和 promise
的写法,在来比较这三者之间的差异。
假设我们定义三个 json
文件,我们知道在 node
中任何文件操作相关的代码都是异步执行的,我们先简单来看下:
// a.json
{
"next": "b.json",
"msg": "this is a"
}
// b.json
{
"next": "c.json",
"msg": "this is b"
}
// c.json
{
"next": null,
"msg": "this is c"
}
项目需求:我们需要先读取
a.json
,然后根据a.json
的next
值去读取b.json
,依次往下读取......
-
callback
function getFileContent(fileName, callback) {
// 当前路径,文件夹 files,要读取的文件名
const fullFileName = path.resolve(__dirname, 'files', fileName)
fs.readFile(fullFileName, (err, data) => {
if (err) {
console.log(err)
return
}
callback(
JSON.parse(data.toString())
)
})
// 利用 callback 来实现
getFileContent('a.json', aData => {
console.log('a data:', aData.msg)
getFileContent(aData.next, bData => {
console.log('b data:', bData.msg)
getFileContent(bData.next, cData => {
console.log('c data:', cData.msg)
})
})
})
callback
回调地狱肯定都知道,如果这是一个5层回调乃至10层,基本写着写着我们就绕晕了.......让我们来认识一下更优雅的写法 Promise
。
-
Promise
// 首先将代码封装成 Promise 写法
function getFileContent(fileName) {
const fullFileName = path.resolve(__dirname, 'files', fileName)
return new Promise((resolve, reject) => {
fs.readFile(fullFileName, (err, data) => {
if (err) {
reject(err)
return
}
resolve(
JSON.parse(data.toString())
)
})
})
}
// 使用 Promise 的 then() 方法链式调用来执行
getFileContent('a.json').then(aData => {
console.log('a data:', aData.msg)
return getFileContent(aData.next)
}).then(bData => {
console.log('b data:', bData.msg)
return getFileContent(bData.next)
}).then(cData => {
console.log('c data:', cData.msg)
})
可以看到 Promise
通过 then()
的回调方法处理异步请求结果更优雅,不会出现嵌套的回调地狱。不了解 Promise
写法的可以去看我写的 Promise基础详解。
既然有了 Promise
写法,那么新出的 async/await
又是什么鬼呢,其实我们可以把它理解为 Promise
的一种语法糖写法,因为 await
其实等待执行的还是必须是一个 Promise
,还是来看栗子吧
// 首先将代码封装成 Promise 写法,这一步和 Promise 中一样
function getFileContent(fileName) {
const fullFileName = path.resolve(__dirname, 'files', fileName)
return new Promise((resolve, reject) => {
fs.readFile(fullFileName, (err, data) => {
if (err) {
reject(err)
return
}
resolve(
JSON.parse(data.toString())
)
})
})
}
// 使用 async/await 来实现
async function getReadFile() {
let aData = await getFileContent('a.json')
let bData = await getFileContent(aData.next)
let cData = await getFileContent(bData.next)
console.log(aData.msg)
console.log(bData.msg)
console.log(cData.msg)
}
getReadFile()
上面我们优化了一下写法,将打印放在了最下面,因为它里面没有写任何回调函数,所以async/await
更像是将异步当成了同步来处理,使得我们的代码可以写的更优雅。这里我们要认识:
-
async
后面必修要跟一个函数 -
await
后面必须跟一个Promise
对象,获取resolve
的值 - 两者必须配套书写,
await
必须包裹在async
函数里, -
async
函数执行返回的也是一个Promise
对象 -
try-catch
截获promise
中的reject
的值
// async 返回的也是一个 Promise 对象,如下:
getReadFile().then(res => {
console.log(111)
})
// try-catch 截获 promise 中 reject 的值
// aData 中并不存在 next1,通过 try cantch 来进行校验
async function getReadFile() {
tyr {
let aData = await getFileContent('a.json')
let bData = await getFileContent(aData.next1)
let cData = await getFileContent(bData.next)
} catch (err) {
console.log(err)
console.log(111)
}
}
getReadFile()
所以说我们可以把它理解为 Promise 的一个语法糖,写到这里,小伙伴应该清楚了吧~~~
网友评论