XHR的封装

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-12-21

/** query请求时,url参数拼接 */
function addUrlParam(url: string, name: string, value: string): string {
  let newUrl = url;
  newUrl += (url.indexOf('?') === -1 ? '?' : '&');// 没有?加? 有问号加&
  newUrl += `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
  return newUrl;
}

/** xhr请求入参 */
export interface RequestOptions {
  url: string;
  method: string;
  params?: Record<string, any>;
  data?: Record<string, any>;
  timeout?: number;
  headers?: Record<string, any>;
  dataType?: XMLHttpRequestResponseType;
}

export function xhr(options: RequestOptions): Promise<any> {
  const xhr = new XMLHttpRequest();
  return new Promise((resolve, reject) => {
    const {
      url, method, timeout, data = {}, headers, dataType,
    } = options;
    let newUrl = url;
    xhr.responseType = dataType || 'json';
    xhr.timeout = timeout || 10000;
    xhr.withCredentials = true;

    // 处理GET参数拼接
    if (method.match(/get/i)) {
      if (options.params) {
        Object.keys(options.params).forEach((key: string) => {
          newUrl = addUrlParam(newUrl, key, options.params?.[key]);
        });
      }
    }

    xhr.open(method.toLowerCase(), newUrl);

    // 处理请求头
    if (headers) {
      Object.keys(headers).forEach((key: string) => {
        xhr.setRequestHeader(key, headers[key]);
      });
    }

    // 处理超时
    xhr.ontimeout = function onTimeout() {
      reject(new Error('timeout'));
    };

    // 处理请求中断
    xhr.onabort = function onAbort() {
      reject(new Error('XMLHTTPRequest abort'));
    };

    // 处理请求错误
    xhr.onerror = function onError() {
      reject(new Error('XMLHTTPRequest error'));
    };

    // 处理请求完成
    xhr.onload = function onLoad() {
      if ((xhr.status >= 200 && xhr.status <= 300) || xhr.status === 304) {
        resolve(xhr.response);
      } else {
        reject(new Error('status error'));
      }
    };

    try {
      // 处理post请求体
      if (method.match(/post/i)) {
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify(data));
      } else {
        // eslint-disable-next-line no-null/no-null
        xhr.send(null);
      }
    } catch (error) {
      reject(new Error('network error'));
    }
  });
}