接上文
故事背景
常规情况下,业务一般拆分到较小的组件,一般涉及 1-2 个请求,使用单个函数等调用及处理错误会比较清晰,但当连续多个请求依次串行调用,业务逻辑可能就是下面这种结构了。
不仅包含多个维度,每个维度的各个需求连续调用,等等层层叠加之后,代码如果用回调甚至 Promise 链式调用的方式逐渐产生结构不清晰或者代码冗余的问题,所以 async & await 应运而生,这里的 await-to-js
就是其中一个优化选择。
优雅的 demo
为什么选择 await-to-js
? 看下面的 demo 就知道它有多优雅了。
import { to } from "await-to-js";
// 底层原子函数
async function generate() {
return axios.get(generateUrl);
}
async function match(payload) {
return axios.post(matchUrl, payload);
}
async function save(payload) {
return axios.post(saveUrl, payload);
}
// 流程处理中心(数据)
async function flow() {
const [err1, r1] = await to(generate());
if (err1) return [err1]; // return axiosError(err1)
const [err2, r2] = await to(match(r1.data.data));
if (err2) return [err2];
const [err3, r3] = await to(save(r2.data.data));
if (err3) return [err3];
return [null, r3];
}
// 用户触发函数,(状态管理),loading 之类
async function onClick() {
const [err, result] = await flow();
if (err) axiosError(err);
else setResult(result);
}
源码分析
源码包含注释总共 22 行,一个高阶包裹函数 to
。
- 传入一个 Promise(axios)
- 返回一个 Promise;
- 成功 await 得到结果 [null,data];
第一个返回 null 可以理解为,第一个位置赋值为 null,而不是没有
- 失败 await 得到结果 [err,undefined];
第二个返回 undefined 可以理解为,没有第二个数据,没经历赋值,所以还是 undefined 类型
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to<T, U = Error> (
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt);
return [parsedError, undefined];
}
return [err, undefined];
});
}
export default to;
to
函数一般结合 await
使用,比如上面的流程处理函数,await 可以接收到 promise 的回调函数的返回结果,无论是 then
还是 catch
;
// 流程处理中心(数据)
async function flow() {
const [err1, r1] = await to(generate());
if (err1) return [err1]; // return axiosError(err1)
const [err2, r2] = await to(match(r1.data.data));
if (err2) return [err2];
const [err3, r3] = await to(save(r2.data.data));
if (err3) return [err3];
return [null, r3];
}
提出疑问,下回分析
从上面的源码我们应该可以提出几个疑问:
比如,为什么 await 可以接收 catch 和 then 的第一个函数返回结果,而没有抛异常呢?
比如,promise 的 catch 可以连续多个调用吗?
比如,promise 的 catch 和 finally 区别是什么?都会执行吗?
…
原文链接:https://juejin.cn/post/7337135278634614834 作者:egolink