[web] 使用Promise封装fetch实现网络超时,终止请求的功能

转载自:https://www.jianshu.com/p/d66421c826ae

本文参考了Fetch进阶指南

缘起

fetch网络请求没有timeout机制,也没有about机制。
而日常开发过程中,必定要对请求超时做处理,也要及时终止不需要的网络请求。
所以,就需要自己封装fetch来实现。

实现

Promise.race(promise1,promise2,...) 方法返回一个Promise对象, 只要参数中任意一个Promise 被 resolve 或者 reject 后, 外部的Promise 就会以相同的值被 resolve 或者 reject.

import React, {Component} from 'react';

/**
 * 使用Promise封装Fetch,具有网络超时、请求终止的功能
 */
class NetUtil extends Component {

    static baseUrl = "http://xxxx:81/api/";
    static token = '';

    /**
     * post请求
     * url : 请求地址
     * data : 参数(Json对象)
     * callback : 回调函数
     * */
    static fetch_request(url, method, params = '') {
        let header = {
            'Accept': 'application/json',
            'Content-Type': 'application/json;charset=UTF-8',
            'accesstoken': NetUtil.token,
        }
        let promise = null;
        if (params == '') {
            promise = new Promise((resolve, reject) => {
                fetch(NetUtil.baseUrl + url, {method: method, headers: header})
                    .then(response => response.json())
                    .then(responseData => resolve(responseData))
                    .then(err => reject(err))
            })
        } else {
            promise = new Promise((resolve, reject) => {
                fetch(NetUtil.baseUrl + url, {method: method, headers: header, body: JSON.stringify(params)})
                    .then(response => response.json())
                    .then(responseData => resolve(responseData))
                    .then(err => reject(err))
            })
        }
        return NetUtil.warp_fetch(promise);
    }

    /**
     * 创建两个promise对象,一个负责网络请求,另一个负责计时,如果超过指定时间,就会先回调计时的promise,代表网络超时。
     * @param {Promise} fetch_promise    fetch请求返回的Promise
     * @param {number} [timeout=10000]   单位:毫秒,这里设置默认超时时间为10秒
     * @return 返回Promise
     */
    static warp_fetch(fetch_promise, timeout = 10000) {
        let timeout_fn = null;
        let abort = null;
        //创建一个超时promise
        let timeout_promise = new Promise(function (resolve, reject) {
            timeout_fn = function () {
                reject('网络请求超时');
            };
        });
        //创建一个终止promise
        let abort_promise = new Promise(function (resolve, reject) {
            abort = function () {
                reject('请求终止');
            };
        });
        //竞赛
        let abortable_promise = Promise.race([
            fetch_promise,
            timeout_promise,
            abort_promise,
        ]);
        //计时
        setTimeout(timeout_fn, timeout);
        //终止
        abortable_promise.abort = abort;
        return abortable_promise;
    }
}

export default NetUtil;

 

posted @ 2020-03-30 18:00  demoblog  阅读(879)  评论(0编辑  收藏  举报