npx create-react-app zaxios --typescript
cd create-react-app
yarn add axios @types/axios qs @types/qs parse-headers
yarn add express body-parser
yarn start
src\index.tsx
import axios, { AxiosResponse } from './axios';
const baseURL = 'http://localhost:8080';
export interface User {
username: string;
password: string;
}
let user: User = {
username: 'zhufeng',
password: '123456'
};
axios({
method: 'get',
url: baseURL + '/get',
params: user
}).then((response: AxiosResponse) => {
console.log(response);
return response.data;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
console.log(error);
});
src\axios\index.tsx
import Axios from './Axios';
import { AxiosInstance } from './types';
function createInstance(): AxiosInstance {
let context = new Axios();
let instance = Axios.prototype.request.bind(context);
instance = Object.assign(instance, Axios.prototype, context);
return instance as AxiosInstance;
}
var axios = createInstance();
export default axios;
export * from './types';
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
import qs from 'qs';
import parse from 'parse-headers';
class Axios {
request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return this.dispatchRequest(config);
}
dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse> {
return new Promise((resolve, reject) => {
let { method = 'get', url, params } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
url = url + (url.indexOf('?') == -1 ? '?' : '&') + paramsString;
}
request.open(method, url, true);
request.responseType = 'json';
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
resolve(response);
} else {
reject('请求失败');
}
}
}
request.send();
});
}
}
export default Axios;
src\axios\types.tsx
export type Methods = 'GET' | 'get' | 'POST' | 'post' | 'PUT' | 'put' | 'DELETE' | 'delete';
export interface AxiosInstance {
<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>
}
export interface AxiosRequestConfig {
url: string;
method?: Methods;
params?: Record<string, any>
}
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
import axios, { AxiosResponse } from './axios';
const baseURL = 'http://localhost:8080';
export interface User {
username: string;
password: string;
}
let user: User = {
username: 'zhufeng',
password: '123456'
};
axios({
+ method: 'post',
+ url: baseURL + '/post',
+ headers: { 'Content-Type': 'application/json' },
+ data: user,
}).then((response: AxiosResponse) => {
console.log(response);
return response.data;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
console.log(error);
});
src\axios\types.tsx
export type Methods = 'GET' | 'get' | 'POST' | 'post' | 'PUT' | 'put' | 'DELETE' | 'delete';
export interface AxiosInstance {
<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>
}
export interface AxiosRequestConfig {
url: string;
method?: Methods;
params?: Record<string, any>;
+ data?: Record<string, any>;
+ headers?: Record<string, any>;
}
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
import qs from 'qs';
import parse from 'parse-headers';
class Axios {
request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return this.dispatchRequest(config);
}
dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse> {
return new Promise((resolve, reject) => {
+ let { method = 'get', url, params, headers, data } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
url = url + (url.indexOf('?') == -1 ? '?' : '&') + paramsString;
}
request.open(method, url, true);
request.responseType = 'json';
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
resolve(response);
} else {
reject('请求失败');
}
}
}
+ if (headers) {
+ for (let key in headers) {
+ request.setRequestHeader(key, headers[key]);
+ }
+ }
+ let body: string | null = null;
+ if (data && typeof data == 'object') {
+ body = JSON.stringify(data);
+ }
+ request.send(body);
});
}
}
export default Axios;
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
import qs from 'qs';
import parse from 'parse-headers';
class Axios {
request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return this.dispatchRequest(config);
}
dispatchRequest(config: AxiosRequestConfig): Promise<AxiosResponse> {
return new Promise((resolve, reject) => {
+ let { method = 'get', url, params, headers, data, timeout } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
url = url + (url.indexOf('?') == -1 ? '?' : '&') + paramsString;
}
request.open(method, url, true);
request.responseType = 'json';
request.onreadystatechange = () => {
+ if (request.readyState === 4 && request.status !== 0) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
resolve(response);
} else {
+ reject(new Error(`Request failed with status code ${request.status}`));
}
}
}
if (headers) {
for (let key in headers) {
request.setRequestHeader(key, headers[key]);
}
}
let body: string | null = null;
if (data && typeof data == 'object') {
body = JSON.stringify(data);
}
+ request.onerror = () => { //网络异常
+ reject(new Error('Network Error'));
+ }
+ if (timeout) {
+ request.timeout = timeout;
+ request.ontimeout = () => { //超时异常
+ reject(new Error(`timeout of ${timeout}ms exceeded`));
+ }
+ }
request.send(body);
});
}
}
export default Axios;
+setTimeout(() => {
axios({
method: 'post',
url: baseURL + '/post',
headers: { 'Content-Type': 'application/json' },
data: user,
}).then((response: AxiosResponse) => {
console.log(response);
return response.data;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
console.log(error);
});
+}, 5000);
axios({
method: 'post',
+ url: baseURL + '/post_timeout?timeout=3000',
headers: { 'Content-Type': 'application/json' },
+ timeout: 1000,
data: user,
}).then((response: AxiosResponse) => {
console.log(response);
return response.data;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
console.log(error);
});
axios({
method: 'post',
+ url: baseURL + '/post_status?code=300',
headers: { 'Content-Type': 'application/json' },
timeout: 1000,
data: user,
}).then((response: AxiosResponse) => {
console.log(response);
return response.data;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
console.log(error);
});
src\index.tsx
import axios from './axios'
import { AxiosResponse, AxiosRequestConfig } from './axios';
const baseURL = 'http://localhost:8080';
interface User {
username: string;
password: string;
}
let user: User = {
username: 'zhufeng',
password: '123456'
};
+console.time('cost');
+axios.interceptors.request.use((config: AxiosRequestConfig) => {
+ console.timeEnd('cost');
+ config.headers!.name += '1';
+ return config;
+ //return Promise.reject('在1处失败了!');
+})
+let request_interceptor = axios.interceptors.request.use((config: AxiosRequestConfig) => {
+ config.headers!.name += '2';
+ return config;
+})
+axios.interceptors.request.use((config: AxiosRequestConfig) => {
+ return new Promise<AxiosRequestConfig>(function (resolve) {
+ setTimeout(function () {
+ config.headers!.name += '3';
+ resolve(config);
+ }, 3000);
+ });
+})
+axios.interceptors.request.eject(request_interceptor);
+axios.interceptors.response.use((response: AxiosResponse) => {
+ response.data.username += '1'
+ return response;
+})
+let response_interceptor = axios.interceptors.response.use((response: AxiosResponse) => {
+ response.data.username += '2'
+ return response;
+})
+axios.interceptors.response.use((response: AxiosResponse) => {
+ response.data.username += '3';
+ return response;
+ //return Promise.reject('失败了');
+})
+axios.interceptors.response.eject(response_interceptor);
axios<User>({
method: 'post',
+ url: baseURL + '/post',
+ headers: { 'Content-Type': 'application/json', name: 'name' },
data: user,
+}).then((response: AxiosRequestConfig | AxiosResponse<User>) => {
console.log(response);
console.timeEnd('cost');
+ return response.data as User;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
console.log('error', error);
});
src\axios\types.tsx
+import AxiosInterceptorManager from './AxiosInterceptorManager';
export type Methods = 'GET' | 'get' | 'POST' | 'post' | 'PUT' | 'put' | 'DELETE' | 'delete';
export interface AxiosInstance {
<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
+ interceptors: {
+ request: AxiosInterceptorManager<AxiosRequestConfig>;
+ response: AxiosInterceptorManager<AxiosResponse>;
+ };
}
export interface AxiosRequestConfig {
url: string;
method?: Methods;
params?: Record<string, any>;
data?: Record<string, any>;
headers?: Record<string, any>;
timeout?: number;
}
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
src\axios\AxiosInterceptorManager.ts
export interface OnFulfilledFn<V> {
(value: V): V | Promise<V>
}
export interface OnRejectedFn {
(error: any): any
}
export interface Interceptor<T = any> {
onFulfilled: OnFulfilledFn<T>
onRejected?: OnRejectedFn
}
export default class InterceptorManager<V> {
private interceptors: Array<Interceptor<V> | null> = []
use(onFulfilled: OnFulfilledFn<V>, onRejected?: OnRejectedFn): number {
this.interceptors.push({
onFulfilled,
onRejected
})
return this.interceptors.length - 1;
}
eject(id: number): void {
if (this.interceptors[id]) {
this.interceptors[id] = null;
}
}
}
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
+import AxiosInterceptorManager, { Interceptor } from './AxiosInterceptorManager';
import qs from 'qs';
import parse from 'parse-headers';
+interface Interceptors {
+ request: AxiosInterceptorManager<AxiosRequestConfig>;
+ response: AxiosInterceptorManager<AxiosResponse>;
+}
class Axios {
+ public interceptors: Interceptors = {
+ request: new AxiosInterceptorManager<AxiosRequestConfig>(),
+ response: new AxiosInterceptorManager<AxiosResponse>()
+ }
+ request<T>(config: AxiosRequestConfig): Promise<AxiosRequestConfig | AxiosResponse<T>> {
- return this.dispatchRequest(config);
+ const chain: Interceptor[] = [
+ {
+ onFulfilled: this.dispatchRequest,
+ onRejected: undefined
+ }
+ ]
+ this.interceptors.request.interceptors.forEach((interceptor: Interceptor<AxiosRequestConfig> | null) => {
+ interceptor && chain.unshift(interceptor);
+ })
+ this.interceptors.response.interceptors.forEach((interceptor: Interceptor<AxiosResponse<T>> | null) => {
+ interceptor && chain.push(interceptor)
+ })
+ let promise: Promise<AxiosRequestConfig | AxiosResponse<T>> = Promise.resolve(config);
+ while (chain.length) {
+ const { onFulfilled, onRejected } = chain.shift()!;
+ promise = promise.then(onFulfilled, onRejected);
+ }
+ return promise;
+ }
+ dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
+ return new Promise<AxiosResponse<T>>((resolve, reject) => {
let { method = 'get', url, params, headers, data, timeout } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
url = url + (url.indexOf('?') == -1 ? '?' : '&') + paramsString;
}
request.open(method, url, true);
request.responseType = 'json';
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status !== 0) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
resolve(response);
} else {
reject(new Error(`Request failed with status code ${request.status}`));
}
}
}
if (headers) {
for (let key in headers) {
request.setRequestHeader(key, headers[key]);
}
}
let body: string | null = null;
if (data && typeof data == 'object') {
body = JSON.stringify(data);
}
request.onerror = () => { //网络异常
reject(new Error('Network Error'));
}
if (timeout) {
request.timeout = timeout;
request.ontimeout = () => { //超时异常
reject(new Error(`timeout of ${timeout}ms exceeded`));
}
}
request.send(body);
});
}
}
export default Axios;
src\axios\types.tsx
export interface AxiosRequestConfig extends Record<string, any> {
+ url?: string;
method?: Methods;
params?: Record<string, any>;
data?: Record<string, any>;
headers?: Record<string, any>;
timeout?: number;
}
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
import AxiosInterceptorManager, { Interceptor } from './AxiosInterceptorManager';
import qs from 'qs';
import parse from 'parse-headers';
interface Interceptors {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
}
+let defaults: AxiosRequestConfig = {
+ method: 'get',
+ timeout: 0,
+ headers: {
+ common: {
+ accept: 'application/json'
+ }
+ }
+}
+let getStyleMethods = ['get', 'head', 'delete', 'options'];
+getStyleMethods.forEach((method: string) => {
+ defaults.headers![method] = {};
+});
+let postStyleMethods = ['put', 'post', 'patch'];
+postStyleMethods.forEach((method: string) => {
+ defaults.headers![method] = {};
+});
+let allMethods = [...getStyleMethods, ...postStyleMethods];
class Axios {
+ public defaults: AxiosRequestConfig = defaults;
public interceptors: Interceptors = {
request: new AxiosInterceptorManager<AxiosRequestConfig>(),
response: new AxiosInterceptorManager<AxiosResponse>()
}
request<T>(config: AxiosRequestConfig): Promise<AxiosRequestConfig | AxiosResponse<T>> {
//return this.dispatchRequest(config);
+ config.headers = Object.assign(this.defaults.headers, config.headers);
const chain: Interceptor[] = [
{
onFulfilled: this.dispatchRequest,
onRejected: undefined
}
]
this.interceptors.request.interceptors.forEach((interceptor: Interceptor<AxiosRequestConfig> | null) => {
interceptor && chain.unshift(interceptor);
})
this.interceptors.response.interceptors.forEach((interceptor: Interceptor<AxiosResponse<T>> | null) => {
interceptor && chain.push(interceptor)
})
let promise: Promise<AxiosRequestConfig | AxiosResponse<T>> = Promise.resolve(config);
while (chain.length) {
const { onFulfilled, onRejected } = chain.shift()!;
promise = promise.then(onFulfilled, onRejected);
}
return promise;
}
dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
return new Promise<AxiosResponse<T>>((resolve, reject) => {
let { method = 'get', url, params, headers, data, timeout } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
+ url = url + (url!.indexOf('?') == -1 ? '?' : '&') + paramsString;
}
+ request.open(method, url!, true);
request.responseType = 'json';
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status !== 0) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
resolve(response);
} else {
reject(new Error(`Request failed with status code ${request.status}`));
}
}
}
+ if (headers) {
+ for (let key in headers) {
+ if (key === 'common' || allMethods.includes(key)) {
+ for (let key2 in headers[key]) {
+ request.setRequestHeader(key2, headers[key][key2]);
+ }
+ } else {
+ request.setRequestHeader(key, headers[key]);
+ }
+ }
+ }
let body: string | null = null;
if (data && typeof data == 'object') {
body = JSON.stringify(data);
}
request.onerror = () => { //网络异常
reject(new Error('Network Error'));
}
if (timeout) {
request.timeout = timeout;
request.ontimeout = () => { //超时异常
reject(new Error(`timeout of ${timeout}ms exceeded`));
}
}
request.send(body);
});
}
}
export default Axios;
src\axios\types.tsx
export interface AxiosRequestConfig extends Record<string, any> {
url?: string;
method?: Methods;
params?: Record<string, any>;
data?: Record<string, any>;
headers?: Record<string, any>;
timeout?: number;
+ transformRequest?: (data: Record<string, any>, headers: Record<string, any>) => any;
+ transformResponse?: (data: any) => any;
}
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
import AxiosInterceptorManager, { Interceptor } from './AxiosInterceptorManager';
import qs from 'qs';
import parse from 'parse-headers';
interface Interceptors {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
}
let defaults: AxiosRequestConfig = {
method: 'get',
timeout: 0,
headers: {
common: {
accept: 'application/json'
}
},
+ transformRequest: function (data: Record<string, any>, headers: Record<string, any>) {
+ headers['content-type'] = 'application/x-www-form-urlencoded';
+ return qs.stringify(data);
+ },
+ transformResponse(data: any) {
+ if (typeof data == 'string')
+ data = JSON.parse(data);
+ return data;
+ },
}
let getStyleMethods = ['get', 'head', 'delete', 'options'];
getStyleMethods.forEach((method: string) => {
defaults.headers![method] = {};
});
let postStyleMethods = ['put', 'post', 'patch'];
postStyleMethods.forEach((method: string) => {
defaults.headers![method] = {};
});
let allMethods = [...getStyleMethods, ...postStyleMethods];
class Axios {
public defaults: AxiosRequestConfig = defaults;
public interceptors: Interceptors = {
request: new AxiosInterceptorManager<AxiosRequestConfig>(),
response: new AxiosInterceptorManager<AxiosResponse>()
}
request<T>(config: AxiosRequestConfig): Promise<AxiosRequestConfig | AxiosResponse<T>> {
//return this.dispatchRequest(config);
+ if (config.transformRequest && config.data)
+ config.data = config.transformRequest(config.data, config.headers = {});
config.headers = Object.assign(this.defaults.headers, config.headers);
const chain: Interceptor[] = [
{
onFulfilled: this.dispatchRequest,
onRejected: undefined
}
]
this.interceptors.request.interceptors.forEach((interceptor: Interceptor<AxiosRequestConfig> | null) => {
interceptor && chain.unshift(interceptor);
})
this.interceptors.response.interceptors.forEach((interceptor: Interceptor<AxiosResponse<T>> | null) => {
interceptor && chain.push(interceptor)
})
let promise: Promise<AxiosRequestConfig | AxiosResponse<T>> = Promise.resolve(config);
while (chain.length) {
const { onFulfilled, onRejected } = chain.shift()!;
promise = promise.then(onFulfilled, onRejected);
}
return promise;
}
dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
return new Promise<AxiosResponse<T>>((resolve, reject) => {
let { method = 'get', url, params, headers, data, timeout } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
url = url + (url!.indexOf('?') == -1 ? '?' : '&') + paramsString;
}
request.open(method, url!, true);
request.responseType = 'json';
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status !== 0) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
+ if (config.transformResponse) {
+ response.data = config.transformResponse(response.data);
+ }
resolve(response);
} else {
reject(new Error(`Request failed with status code ${request.status}`));
}
}
}
if (headers) {
for (let key in headers) {
if (key === 'common' || allMethods.includes(key)) {
for (let key2 in headers[key]) {
request.setRequestHeader(key2, headers[key][key2]);
}
} else {
request.setRequestHeader(key, headers[key]);
}
}
}
let body: string | null = null;
if (data && typeof data == 'object') {
body = JSON.stringify(data);
}
request.onerror = () => { //网络异常
reject(new Error('Network Error'));
}
if (timeout) {
request.timeout = timeout;
request.ontimeout = () => { //超时异常
reject(new Error(`timeout of ${timeout}ms exceeded`));
}
}
request.send(body);
});
}
}
export default Axios;
src\index.tsx
import axios from './axios'
import { AxiosResponse, AxiosRequestConfig } from './axios';
interface User {
username: string;
password: string;
}
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios({
method: 'post',
baseURL: 'http://localhost:8080',
url: '/post_timeout?timeout=2000',
timeout: 3000,
cancelToken: source.token
}).then((response: AxiosRequestConfig | AxiosResponse<User>) => {
console.log(response);
return response.data as User;
}).then((data: User) => {
console.log(data);
}).catch(function (error: any) {
if (axios.isCancel(error)) {
console.log('请求取消', error);
} else {
console.log('error', error);
}
});
source.cancel('用户取消请求');
src\axios\types.tsx
export interface AxiosInstance {
<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
+ CancelToken: any;
+ isCancel: any
}
src\axios\cancel.tsx
export class Cancel {
constructor(public reason: string) { }
}
export function isCancel(error: any) {
return error instanceof Cancel;
}
export class CancelToken {
public resolve: any;
source() {
return {
token: new Promise((resolve) => {
this.resolve = resolve;
}),
cancel: (reason: string) => {
this.resolve(new Cancel(reason));
}
}
}
}
src\axios\index.tsx
import Axios from './Axios';
import { AxiosInstance } from './types';
+import { CancelToken, isCancel } from './cancel';
function createInstance(): AxiosInstance {
let context = new Axios();
let instance = Axios.prototype.request.bind(context);
instance = Object.assign(instance, Axios.prototype, context);
return instance as AxiosInstance;
}
var axios = createInstance();
+axios.CancelToken = new CancelToken();
+axios.isCancel = isCancel;
export default axios;
export * from './types';
src\axios\Axios.tsx
import { AxiosRequestConfig, AxiosResponse } from './types';
import AxiosInterceptorManager, { Interceptor } from './AxiosInterceptorManager';
import qs from 'qs';
import parse from 'parse-headers';
interface Interceptors {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
}
let defaults: AxiosRequestConfig = {
method: 'get',
timeout: 0,
headers: {
common: {
accept: 'application/json'
}
},
transformRequest: function (data: Record<string, any>, headers: Record<string, any>) {
headers['content-type'] = 'application/x-www-form-urlencoded';
return qs.stringify(data);
},
transformResponse(data: any) {
if (typeof data == 'string')
data = JSON.parse(data);
return data;
},
}
let getStyleMethods = ['get', 'head', 'delete', 'options'];
getStyleMethods.forEach((method: string) => {
defaults.headers![method] = {};
});
let postStyleMethods = ['put', 'post', 'patch'];
postStyleMethods.forEach((method: string) => {
defaults.headers![method] = {};
});
let allMethods = [...getStyleMethods, ...postStyleMethods];
class Axios {
public defaults: AxiosRequestConfig = defaults;
public interceptors: Interceptors = {
request: new AxiosInterceptorManager<AxiosRequestConfig>(),
response: new AxiosInterceptorManager<AxiosResponse>()
}
request<T>(config: AxiosRequestConfig): Promise<AxiosRequestConfig | AxiosResponse<T>> {
//return this.dispatchRequest(config);
if (config.transformRequest && config.data)
config.data = config.transformRequest(config.data, config.headers = {});
config.headers = Object.assign(this.defaults.headers, config.headers);
config = Object.assign(this.defaults, config);
if (!config.url!.startsWith('http') && config.baseURL) {
config.url = config.baseURL + config.url;
}
const chain: Interceptor[] = [
{
onFulfilled: this.dispatchRequest,
onRejected: undefined
}
]
this.interceptors.request.interceptors.forEach((interceptor: Interceptor<AxiosRequestConfig> | null) => {
interceptor && chain.unshift(interceptor);
})
this.interceptors.response.interceptors.forEach((interceptor: Interceptor<AxiosResponse<T>> | null) => {
interceptor && chain.push(interceptor)
})
let promise: Promise<AxiosRequestConfig | AxiosResponse<T>> = Promise.resolve(config);
while (chain.length) {
const { onFulfilled, onRejected } = chain.shift()!;
promise = promise.then(onFulfilled, onRejected);
}
return promise;
}
dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
return new Promise<AxiosResponse<T>>((resolve, reject) => {
let { method = 'get', url, params, headers, data, timeout } = config;
let request: XMLHttpRequest = new XMLHttpRequest();
if (params) {
let paramsString = qs.stringify(params);
url = url + (url!.indexOf('?') === -1 ? '?' : '&') + paramsString;
}
request.open(method, url!, true);
request.responseType = 'json';
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status !== 0) {
if (request.status >= 200 && request.status < 300) {
let response: AxiosResponse = {
data: request.response,
status: request.status,
statusText: request.statusText,
headers: parse(request.getAllResponseHeaders()),
config: config,
request
}
if (config.transformResponse) {
response.data = config.transformResponse(response.data);
}
resolve(response);
} else {
reject(new Error(`Request failed with status code ${request.status}`));
}
}
}
if (headers) {
for (let key in headers) {
if (key === 'common' || allMethods.includes(key)) {
for (let key2 in headers[key]) {
request.setRequestHeader(key2, headers[key][key2]);
}
} else {
request.setRequestHeader(key, headers[key]);
}
}
}
let body: string | null = null;
if (data && typeof data == 'object') {
body = JSON.stringify(data);
}
request.onerror = () => { //网络异常
reject(new Error('Network Error'));
}
+ if (config.cancelToken) {
+ config.cancelToken.then((reason: string) => {
+ request.abort();
+ reject(reason);
+ });
+ }
if (timeout) {
request.timeout = timeout;
request.ontimeout = () => { //超时异常
reject(new Error(`timeout of ${timeout}ms exceeded`));
}
}
request.send(body);
});
}
}
export default Axios;
let express = require('express');
let bodyParser = require('body-parser');
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(function (req, res, next) {
res.set({
'Access-Control-Allow-Origin': 'http://localhost:3000',
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Methods': 'GET,POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type,name'
});
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
app.get('/get', function (req, res) {
res.json(req.query);
});
app.post('/post', function (req, res) {
res.json(req.body);
});
app.post('/post_timeout', function (req, res) {
let { timeout } = req.query;
console.log(req.query);
if (timeout) {
timeout = parseInt(timeout);
} else {
timeout = 0;
}
setTimeout(function () {
res.json(req.body);
}, timeout);
});
app.post('/post_status', function (req, res) {
let { code } = req.query;
if (code) {
code = parseInt(code);
} else {
code = 200;
}
res.statusCode = code;
res.json(req.body);
});
app.listen(8080);