react-native网络请求fetch使用(十一)

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,使用也更容易。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值