react-native网络请求fetch使用封装拦截器;fetch常见使用方式:
Typescript方式使用fetch拦截器:
export class FetchInterceptor {
public interceptors: any[] = [];
public interceptor(fetch: (input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>,
options: { input: RequestInfo, init?: RequestInit | undefined }) {
const reversedInterceptors = this.interceptors.reduce((array, interceptor) => [...[interceptor], array]);
let promise = Promise.resolve(options);
reversedInterceptors.forEach(({ request, requestError }: any) => {
if (request || requestError) {
promise = promise.then(opt => request(opt.input, opt.init), requestError);
}
});
let responsePromise = promise.then(opt => fetch(opt.input, opt.init));
reversedInterceptors.forEach(({ response, responseError }: any) => {
if (response || responseError) {
responsePromise = responsePromise.then((resp: Response) => {
return response(resp);
});
}
});
return responsePromise;
}
}
window.fetch = ((fetch) => {
return (input: RequestInfo, init?: RequestInit | undefined) => {
return fetchInterceptor.interceptor(fetch, { input, init });
};
})(window.fetch);
export const fetchInterceptor = new FetchInterceptor();
//how to use?
fetchInterceptor.interceptors.push({
request: (input: string, init: RequestInit) => {
const token = store.getters.getToken;
let headers = new Headers(init.headers);
headers.append('Authorization', '');//这里是自定义请求头
init.headers = headers;
return { input, init };
}
}, {
response: (response: Response) => {
/*自定义方法拦截服务器返回码*/
if (response.status === '') {
router.replace('signin'); //登录
}
return response;
}
})
/*注:以上是全局的fetch设置,在单独组件中可以自由使用fech即可*/
Javascript方式fetch拦截器:
let interceptors = [];
const interceptor = (fetch, ...args) => {
const reversedInterceptors = interceptors.reduce((array, interceptor) => [interceptor].concat(array), []);
const [, opt] = args;
let promise = Promise.resolve(args);
// Register request interceptors
reversedInterceptors.forEach(({ request, requestError }) => {
if (request || requestError) {
promise = promise.then(args => request(...args), requestError);
}
});
// Register fetch call
promise = promise.then(args => fetch(...args));
// Register response interceptors
reversedInterceptors.forEach(({ response, responseError }) => {
if (response || responseError) {
promise = promise.then(res => response(res, opt), err => responseError(err, opt));
}
});
return promise;
};
export const request = ((fetch) => {
return (...args) => {
return interceptor(fetch, ...args);
};
})(fetch);
export const fetchIntercept = {
register: (interceptor) => {
interceptors.push(interceptor);
return () => {
const index = interceptors.indexOf(interceptor);
if (index >= 0) {
interceptors.splice(index, 1);
}
};
},
clear: () => {
interceptors = [];
}
};
//how to use? ?? 在组件引入以下模块即可!!!
fetchIntercept.register({
request(url, config = {}) {
const state = store.getState();
if (state.user.authorization) {
config = merge({}, {
headers: {
'access_token': state.user.authorization
}
}, config);
}
return [/^https?:\/\//.test(url) ? url : `${API}${url}`, config];
},
requestError(error) {
// Called when an error occurred during another 'request' interceptor call
// resolve 后不写 catch
return Promise.resolve(error);
},
response(response) {
const { status, statusText } = response;
if (status === 401) {
statusText && Toast.show(statusText);
autoLogout();
}
const res = response.clone();
const r = response.clone();
return response.json().then((json = {}) => {
const { code } = json;
if (code === 3) {
json.msg = '';
autoLogout();
}
return json;
}).catch(() => res.text()).catch(() => r);
},
responseError() {
// Handle an fetch error
// resolve 后不写 catch
return Promise.resolve({});
}
});
// fetch.shoutMethod(url, config)
const createShortMethods = (...names) => {
names.forEach(name => {
fetch[name] = (url, config = {}) => {
const data = config.data || config.body;
const queryString = data ? ('?' + qs.stringify(data)) : '';
return fetch(url + queryString, Object.assign(config, {
method: name
}));
};
});
};
// fetch.shoutMethod(url, data, config)
const createShortMethodsWithData = (...names) => {
names.forEach(name => {
fetch[name] = (url, data = {}, config = {}) => fetch(url, Object.assign(config, {
method: name,
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}));
});
};
createShortMethods('get', 'delete', 'head', 'jsonp');
createShortMethodsWithData('post', 'put', 'patch');
export default fetch;
//注:此模块加载后会占用原生fech模块命名空间 所以可以在组件中直接使用fetch
以上两块代码拷贝即用,fetch的使用比较简单,拦截器的封装也是很容易的,都是结合Promise来做异步请求,而且fetch的文档也比较晚上,react-native模版项目就集成了这个fetch,使用也更容易。