1. 前言
虽然我们现在已经实现了官方axios
请求取消功能的两种使用方式,但是官方axios
上还有个isCancel
接口还未实现。该接口接收一个异常对象e
作为参数,用来判断该异常是否是由取消请求导致的,如果是的话该异常对象就应该是请求取消的原因;该接口实现起来也不难,我们可以创建一个取消原因Cancel
类,而把请求取消的原因作为该类的实例,这样我们在捕获异常的时候只需判断异常对象是不是Cancel
类的实例,如果是的话,那么它就是请求取消原因,否则就是其他异常。OK,思路就是这样,接下来,我们就来实现它。
2. 定义Cancel接口类型
创建cancel
类之前,我们先在src/types/index.ts
中定义接口类型,如下:
export interface Cancel {
message?: string
}
export interface CancelStatic {
new(message?: string): Cancel
}
我们先定义了Cancel
类的实例对象类型Cancel
,它里面只有一个属性,那就是取消原因message
,接着还定义了Cancel
类的类类型,它里面包含了构造函数属性,构造函数接收取消原因作为参数,返回Cancel
类的实例对象。
3. 创建Cancel类
接口类型定义好之后,我们就来创建Cancel
类,我们在src/cancel
目录下创建Cancel.ts
文件,在该文件内创建Cancel
类,如下:
export default class Cancel {
message: string;
constructor(message:string){
this.message = message
}
}
该类的实现非常简单,就是实例化一个取消原因对象,该对象的message
属性就是请求的取消原因。
4. 创建isCancel方法
创建好Cancel
类之后,我们还应该创建一个isCancel
函数,该函数用来判断异常对象是不是取消原因对象,返回true
或false
。我们在src/cancel
目录下创建isCancel.ts
文件,在该文件内创建isCancel
函数,如下:
import Cancel from "./Cancel";
export default function isCancel(val:any):boolean {
return val instanceof Cancel
}
判断异常对象是不是取消原因对象,我们只需判断它是不是Cancel
类的实例即可。
5. 添加Cancel和isCancel接口
创建好isCancel
函数后,最后,我们将其添加到axios
混合对象上,添加之前,还是要先在axios
混合对象接口定义中添加isCancel
属性,如下:
export interface AxiosStatic extends AxiosInstance {
create(config?: AxiosRequestConfig): AxiosInstance;
CancelToken: CancelTokenStatic;
Cancel: CancelStatic;
isCancel: (value: any) => boolean;
}
添加好接口类型以后,我们就可以在src/axios.ts
中给axios
混合对象添加Cancel
和isCancel
接口了,如下:
import Cancel from "./cancel/Cancel";
import isCancel from "./cancel/isCancel";
axios.Cancel = Cancel;
axios.isCancel = isCancel;
6. 修改之前的取消原因类型
我们现在创建取消原因Cancel
类,所以我们需要将之前写的取消原因message
从string
类型改成Cancel
类型。需要改动如下几个地方:
src/types/index.ts
:
export interface CancelToken {
promise: Promise<Cancel>
reason?: Cancel
}
src/cancel/CancelToken.ts
import { Canceler, CancelExecutor, CancelTokenSource} from "../types";
import Cancel from "./Cancel";
interface ResolvePromise {
(reason?: Cancel): void;
}
export default class CancelToken {
promise: Promise<Cancel>;
reason?: Cancel;
constructor(executor: CancelExecutor) {
let resolvePromise: ResolvePromise;
this.promise = new Promise<Cancel>(resolve => {
resolvePromise = resolve;
});
executor(message => {
if (this.reason) {
return;
}
this.reason = new Cancel(message);
resolvePromise(this.reason);
});
}
static source(): CancelTokenSource {
let cancel!: Canceler;
let token = new CancelToken(c => {
cancel = c;
});
return {
cancel,
token
};
}
}
修改完之后,isCancel
接口就算实现完毕了,接下来,我们就编写demo
测试效果如何。
7. demo编写
我们继续沿用上篇文章的demo
,只需在src/examples/cancel/app.ts
文件中捕获异常的地方添加上本篇文章实现的异常对象判断即可,如下:
axios
.get("/api/cancel", {
cancelToken: new CancelToken(c => {
cancel = c;
})
})
.catch(function(e) {
// 新增
if (axios.isCancel(e)){
console.log(`请求取消原因:${e.message}`);
}
});
然后运行项目,我们打开 chrome
浏览器,访问 http://localhost:8000/ 即可访问我们的 demo
了,我们点击 cancel
,通过F12
的控制台中,我们看到取消原因已经被打印出来了。
(完)