异步回调函数改造
如果你不知道Promise和async await的基本用法,建议学习了之后再往下看。
宇宙节校招的一道题:
- node.js里写一个读取文件的函数
- 将
callback
改造成Promise
或者async
实现
回调函数版本
主要记住node的API大部分回调函数err在前面,data在后面就OK了。
const fs = require('fs');
function readFileCallBack() {
fs.readFile('./test.txt', 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});
}
readFileCallBack();
Promise版本
改成Promise
实现也挺简单的,记住Promise
的方法就行了。我当时还以为是要我使用Promise
实现一个通用的函数,那比较困难,但是其实面试官不是这个意思,他是想让我继续改造上面👆🏻的功能,那就很方便写了。
function readFilePromise() {
return new Promise((resolve, reject) => {
fs.readFile('./test.txt', 'utf8', (err, data) => {
if (err) {
reject(err);
}
resolve(data);
});
});
}
readFilePromise()
.then(
(data) => console.log(data),
(err) => console.error(err)
)
.catch((err) => console.error(err));
这里需要关注的一个概念就是then
里的err处理和catch
里的err处理,它们之间的关系是怎么样的。感兴趣的可以自己去跑一下,总结一句话就是写Promise
一定不要忘了把catch
写在最后,这很关键。
Async版本
然后,继续将这个改变为async await
的形式。Promise虽然改变了callback的情况,将回调变成链式调用,但是Promise的缺点也很明显:首先是不太直观,然后是catch错误的问题,需要写很多重复的代码。
实现将Promise改造为async函数,实现下面这一步其实就完成了大部分:将改造的函数进行Promise化 。因为await后必须紧跟异步任务函数,其他同步的都不生效。此时,上面已经实现了,我只需要拿来用就行了。
async需要注意的是:注意错误处理 ,很多时候会忘记导致错误让程序中断,这是非常严重的失误。
async function readFileAsync() {
try {
const data = await readFilePromise();
console.log(`data:${data}`);
} catch (err) {
console.error(err);
}
}
readFileAsync();
因为fs其实自带Promise,我们可以不用使用之前实现的readFilePromise也能实现这个功能。
// 直接取promise化的fs用
const fs = require('fs').promises;
async function readFileAsync() {
try {
const data = await fs.readFile('./test.txt', 'utf8');
console.log(`data:${data}`);
} catch (err) {
console.error(err);
}
}
readFileAsync();
async函数返回的是Promise实例,也可以这样去处理错误,不过又绕到了Promise上了:
async function readFileAsync() {
const data = await fs.readFile('./test1.txt', 'utf-8');
return data;
}
readFileAsync()
.then(data => console.log(`data:${data}`))
.catch(err => console.error(`err:${err}`))
async的写法看起来就比较像同步函数了,但是async也有一些坑,比如不能写在循环条件里等等。
总结
在将callback转化为Promise或者async函数时,非常非常需要注意的点就是错误处理。如果异步的情况比较复杂,又忘记错误处理的话,测试是不一定能够完全覆盖里面的所有状态的,比较容易出错。
- Promise里的catch err
- async里的try catch