http-request-decorator
v1.1.0
Published
基于 axios 和 ES Decorator ,用更优雅的 AOP 方式实现异步网络请求
Downloads
8
Maintainers
Readme
http-request-decorator
基于 axios 和 ES Decorator ,用更优雅的 AOP 方式实现异步网络请求
Install
npm install http-request-decorator
or use yarn
yarn add http-request-decorator
Example
import {
Get,
Response,
Params,
Header,
requestConfig,
HttpResponse,
} from 'http-request-decorator';
requestConfig.set({
baseURL: 'https://test.api.com',
headers: {
'Cache-Control': 'max-age=0',
'Authorization': 'Bearer foobar'
},
});
type DataRes = {
errcode: number,
errmsg: string,
data: {
foo: string,
bar: number,
other: unknown,
},
};
class MyApp {
@Get('/detail/get')
@Header({ 'Accept': '*/*' })
@Params({ 'default_param': 123 })
fetch(@Params params: Record<string, any>, @Response res?: HttpResponse<DataRes>) {
if (res && res.data) {
console.log(res.data.data.foo);
}
}
onGetDetail() {
const params = { foo: 'bar' };
this.fetch(params);
/**
* 事实上 fetch 函数被包装后也相当于一个异步函数,如果你在 fetch 函数里返回 res,onGetDetail 也可以改写成 async/await 函数:
* async onGetDetail() {
* const params = { foo: 'bar' };
* const res = await this.fetch(params);
* console.log('Response', res);
* }
* 或是 Promise 般调用:this.fetch().then(res => {});
* 这样 res 就被传递过来,onGetDetail 方法里也能处理 http 请求返回结果
* /
}
}
注意1:使用多个方法装饰器时,调用顺序是由里装饰器到外装饰器,而调用 axios 请求逻辑是写在请求方法装饰器里的(如
@Get()
,@Post()
等),所以编写代码时务必把 请求方法装饰器 写在 最上面。
注意2:使用多个参数装饰器时,参数并无指定顺序,但
@Response
,@Exception
在调用函数时是不需要传递实参的,请将其写在形参顺序的最后。
@Get('/foo/bar')
fetch(
@Params params: any,
@Response res?: HttpResponse<DataRes>,
@Exception e?: unknown,
) {
if (!e && res) {
console.log(res);
} else {
console.log(e);
}
}
// 调用时只传 params
{
this.fetch({ foo: 'bar' });
}
Docs
Decorators
Get
包装 GET 请求的方法装饰器,只接受请求的url
参数,使用如@Get('https://demo.someapi.com/foo/bar')
,设置baseUrl
后@Get('/foo/bar')
@Get('/foo/bar') // 设置了 baseUrl
// 未设置 baseUrl 使用完整链接 @Get('https://xxxx/foo/bar')
fetch(@Params params: any) {}
Post
包装 POST 请求的方法装饰器,使用同上Put
包装 PUT 请求的方法装饰器,使用同上Head
包装 HEAD 请求的方法装饰器,使用同上Delete
包装 DELETE 请求的方法装饰器,使用同上Header
包装请求头 headers 的方法装饰器,接受一个对象参数,会对默认请求头里相同字段项进行覆盖
import {
requestConfig,
} from 'http-request-decorator';
requestConfig.set({
headers: {
'Cache-Control': 'no-cache',
'platform': 'ios',
},
});
class MyApp {
@Get('/foo/bar')
// 默认 headers Cache-Control 会被覆盖
// headers {'Cache-Control': 'max-age=0', 'platform': 'ios'}
@Header({ 'Cache-Control': 'max-age=0' })
fetch() {}
}
Params
包装请求参数的 方法/参数 装饰器
class MyApp {
@Get('/foo/bar')
@Params({ foo: 123 }) // 包装静态不变参数
fetch(@Params params: Record<string, any>) {
// 包装动态参数的形参,会覆盖静态参数里的相同项
}
onFetch() {
const params = { bar: 456, foo: 789 };
this.fetch(params);
// 最终参数 { foo: 789, bar: 456 }
}
}
Config
请求配置的方法/参数装饰器。作为方法装饰器时,接受唯一参数类型RequestConfig
;作为参数装饰器时,修饰的参数类型RequestConfig
@Get('/foo/bar')
@Config({ params: { foo: 1, bar: 2 } })
fetch(
@Params params: any,
@Config config: RequestConfig,
@Response res?: HttpResponse,
) {}
Response
包装异步请求返回响应的参数装饰器
class MyApp {
@Get('/foo/bar')
fetch(@Response res?: HttpResponse) {
console.log('The response:', res);
}
}
Exception
包装请求时发生的错误捕获的参数装饰器
class MyApp {
@Get('/foo/bar')
fetch(@Response res?: HttpResponse, @Exception e?: unknown) {
if (!e && res) {
console.log('The response:', res);
}
}
}
Advanced
createMethodDecorator
自定义请求方法装饰器,接受一个HttpMethod
字面量类型的字符串,返回一个方法装饰器,使用同Get
、Post
等
const Patch = createMethodDecorator('PATCH');
class MyApp {
@Patch('/foo/bar')
fetch() {
}
}
requestConfig
请求配置对象,有两个方法set
和get
。set
方法可以设置全局的请求配置对象。参数类型RequestConfig
get
方法返回当前的默认请求配置对象的代理,是只读的。
requestConfig.set({
baseURL: 'https://some-domain.com/api/',
headers: { 'X-Requested-With': 'XMLHttpRequest' },
});
const config = requestConfig.get();
config.baseURL = 'xxx' // 无效
interceptors
axios
的拦截器
interceptors.request.use((config) => {
config.headers.Authorization = 'hello world';
return config;
});
createInstance
创建一个AxiosInstance
,独立隔离的请求配置。参数可选,指定的请求配置。
import { createInstance } from 'http-request-decorator';
const { requestConfig, Get } = createInstance({
baseURL: 'https://api.another.com:8888',
});
包含以下属性,只在该实例生效,使用同上:
- 所有的装饰器
createMethodDecorator
interceptors
requestConfig
Types
LooseObject
type LooseObject = Record<keyof any, any>;
HttpMethod
type Method =
| 'get' | 'GET'
| 'delete' | 'DELETE'
| 'head' | 'HEAD'
| 'options' | 'OPTIONS'
| 'post' | 'POST'
| 'put' | 'PUT'
| 'patch' | 'PATCH'
| 'purge' | 'PURGE'
| 'link' | 'LINK'
| 'unlink' | 'UNLINK'
RequestConfig
interface AxiosRequestConfig {
url?: string;
method?: Method;
baseURL?: string;
transformRequest?: AxiosTransformer | AxiosTransformer[];
transformResponse?: AxiosTransformer | AxiosTransformer[];
headers?: any;
params?: any;
paramsSerializer?: (params: any) => string;
data?: any;
timeout?: number;
timeoutErrorMessage?: string;
withCredentials?: boolean;
adapter?: AxiosAdapter;
auth?: AxiosBasicCredentials;
responseType?: ResponseType;
xsrfCookieName?: string;
xsrfHeaderName?: string;
onUploadProgress?: (progressEvent: any) => void;
onDownloadProgress?: (progressEvent: any) => void;
maxContentLength?: number;
validateStatus?: ((status: number) => boolean) | null;
maxBodyLength?: number;
maxRedirects?: number;
socketPath?: string | null;
httpAgent?: any;
httpsAgent?: any;
proxy?: AxiosProxyConfig | false;
cancelToken?: CancelToken;
decompress?: boolean;
}
HttpResponse
interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}