以 nodejs fs 的 stat 方法为例
回调式
nodejs 早起 api 以回调的方式为主,回调函数第二个参数就是错误❌对象(先处理错误原则)
fs.stat("index.mjs", (err, stats) => {
if (err) {
console.log(err);
return
}
console.log("stats", stats);
});
使用 promise
返回一个数组 [err, res], 将错误❌放在数组第一位,异步结果放在第二位,遵循 promise 的设计原则
纯 promise 链式调用 then/catch
fs.promises
.stat("/stat.tjs")
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
then/catch 方法
const [err1, res1] = await fs.promises
.stat("/stat.tjs")
.then((data) => [null, data])
.catch((err) => [err, null]);
await/then
const [err, res] = await fs.promises.stat("./stat.mjs").then(
(data) => [null, data],
(err) => [err, null]
);
await/then-catch
const [err, res] = await fs.promises
.stat("/stat.tjs")
.then((data) => [null, data])
.catch((err) => [err, null]);
try-catch/await
try {
let data = await fs.promises.stat("./stat.js");
} catch (err) {
console.log("sdf", err);
}
对 promise 进行扩展
如何学习了 Rust, 支持 Rust 中分为 可恢复 / 不可恢复 两种错误;
- panic! 不可恢复,对应了 javascript 中的 throw a error,典型的有 unwrap, 错误是不可恢复,不可继续传递的。下面在 promise 中使用 unwrap 统一处理错误,减少样板代码。
首先 扩展 Promise interface 避免 TS 类型报错:
// promise.d.ts
interface Promise<T> {
/**
* panic a error or return a promise
* @returns A Promise for the completion of the callback.
*/
unwrap(): Promise<T>;
}
以 axios 请求为示例,(考虑到 unwrap 可能成为promise的方法,命名仅供参考)
// 实际扩展原型链 unwrap 方法, 保留 this 使用 function 来声明
Promise.prototype.unwrap = function <T>(): Promise<T> {
return this
.then((res) => res)
.catch((err) => {
throw new Error('promise unwrap failed\n' + err);
});
};
使用, unwrap 中直接 throw 错误,与 Rust panic! 效果一致,不可恢复
const service = axios.create({
baseURL: '/api',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
timeout: 10000,
responseType: 'json',
withCredentials: true,
transformRequest: [(data) => qs.stringify(data)],
});
// 封装 get 请求
export const getRequest = async (url: string, params?: any) => {
const { data: res } = await service.get(url, { params }).unwrap()
return res;
};
生成器
生成器在前端使用场景比较少,使用较多的是 redux-saga 中, 生成器使用 try-catch 捕获错误
function* foo() {
var x =
try {
yield 3;
} catch (err) {
console.log(err)
}
var y = x.toUpperCase();
yield y;
}
var it = foo();
it.next(); // { value:3, done:false }
try {
it.next(42);
} catch (err) {
console.log(err);
}
值的注意的是:生成可以在函数体中捕获 yield 错误,也可以在 gen.next 中使用 try-catch 捕获错误。