函数莫名被Canceled
写了一个aop函数,当执行函数返回结果是一个Promise时,after函数存在多个时,只能触发第一个,其他会被Canceled
aop.ts
type handler = (...args: any[]) => Promise<any> | any;
type afterHandler = (res: afterCallbackResult) => any;
type beforeHandler = (...args: any[]) => any;
interface IAop extends handler {
afterHandlers: afterHandler[];
beforeHandlers: beforeHandler[];
after: (afterFn: afterHandler) => IAop;
before: (beforeFn: beforeHandler) => IAop;
}
interface IAfterSuccess {
status: 'success';
value: any;
}
interface IAfterFail {
status: 'fail';
error: Error;
}
type afterCallbackResult = IAfterSuccess | IAfterFail;
/**
* 返回aop函数
* @param fn
* @returns
*/
function createAop(fn: handler): IAop {
if (typeof fn !== 'function') {
throw TypeError('[aop] fn参数应该是一个函数!');
}
const handler: IAop = function () {
const args = arguments;
const afterHandlers = handler.afterHandlers;
const beforeHandlers = handler.beforeHandlers;
// 执行前置函数
if (Array.isArray(beforeHandlers) && beforeHandlers.length) {
const isEnd = beforeHandlers.some((h) => {
const ret = h.apply(this, args);
// 显示的返回false则终止执行
return ret === false;
});
if (isEnd) return;
}
// 执行当前函数
const ret = fn.apply(this, args);
/* 执行后置函数 */
if (!(Array.isArray(afterHandlers) && afterHandlers.length)) {
return ret;
}
const afterFn = (result: afterCallbackResult) => {
afterHandlers.forEach((h) => {
h.call(this, result);
});
};
// 非promise类型的执行结果
if (Object.prototype.toString.call(ret) !== '[object Promise]') {
afterFn({
status: 'success',
value: ret,
});
return ret;
}
return new Promise((resolve, reject) => {
ret
.then((res: any) => {
resolve(res);
afterFn({
status: 'success',
value: res,
});
})
.catch((err: Error) => {
reject(err);
afterFn({
status: 'fail',
error: err,
});
});
});
};
handler.afterHandlers = [] as afterHandler[];
handler.beforeHandlers = [] as beforeHandler[];
handler.after = function (afterFn: afterHandler): IAop {
if (typeof afterFn !== 'function') {
throw TypeError('[aop.after] "afterFn" 参数应该是一个函数!');
}
handler.afterHandlers.push(afterFn);
return handler;
};
handler.before = function (beforeFn: beforeHandler): IAop {
if (typeof beforeFn !== 'function') {
throw TypeError('[aop.before] "beforeFn" 参数应该是一个函数!');
}
handler.beforeHandlers.push(beforeFn);
return handler;
};
return handler;
}
export default createAop;
测试代码
const a = aop(function (tt: number) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(tt + 1);
}, 1000);
});
})
.before(function (a: number) {
console.log('执行前1', a);
})
.before(function (a: number) {
console.log('执行前2', a);
})
.after(function (res: any) {
console.log('执行结果1:', res);
})
.after(function (res: any) {
console.log('执行结果2:', res);
})
.after(function (res: any) {
console.log('执行结果3:', res);
});
a(33).then((res: number) => {
console.log(res);
});
测试结果
预期的结果
执行前1 33
执行前2 33
34
执行结果1: {status: 'success', value: 34}
执行结果2: {status: 'success', value: 34}
执行结果3: {status: 'success', value: 34}
问题一:如何保证执行顺序,现在after函数在执行结果之前执行了。
问题二:为什么其他的after函数会被Canceled?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我在node和浏览器环境里都测试了,没有你说的情况