封装 AJAX

/**
 * 封装 AJAX
 * @param {Object} options - 请求配置对象
 * @param {string} options.url - 请求URL
 * @param {string} [options.method='GET'] - 请求方法 (GET, POST, PUT, DELETE等)
 * @param {Object} [options.data=null] - 请求数据
 * @param {Object} [options.headers={}] - 自定义请求头
 * @param {number} [options.timeout=10000] - 超时时间(毫秒)
 * @param {string} [options.responseType=''] - 响应类型 (text, json, blob等)
 * @returns {Promise} 返回Promise对象
 */
function request(options) {
  return new Promise((resolve, reject) => {
    // 参数校验
    if (!options || !options.url) {
      reject(new Error('URL is required'));
      return;
    }

    const xhr = new XMLHttpRequest();
    const { 
      url, 
      method = 'GET', 
      data = null, 
      headers = {}, 
      timeout = 10000,
      responseType = ''
    } = options;

    // 初始化请求
    xhr.open(method.toUpperCase(), url, true);
    
    // 设置响应类型
    if (responseType) {
      xhr.responseType = responseType;
    }

    // 设置超时
    xhr.timeout = timeout;
    xhr.ontimeout = () => {
      reject(new Error(`Request timed out after ${timeout}ms`));
    };

    // 设置请求头
    if (data && !headers['Content-Type']) {
      xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
    }
    
    Object.keys(headers).forEach(key => {
      xhr.setRequestHeader(key, headers[key]);
    });

    // 处理响应
    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        try {
          // 自动解析JSON响应
          const response = responseType === 'json' || xhr.getResponseHeader('Content-Type')?.includes('application/json')
            ? JSON.parse(xhr.responseText)
            : xhr.response;
          resolve(response);
        } catch (e) {
          reject(new Error('Failed to parse response as JSON'));
        }
      } else {
        reject(new Error(`Request failed with status ${xhr.status}: ${xhr.statusText}`));
      }
    };

    xhr.onerror = () => {
      reject(new Error('Network request failed'));
    };

    // 发送请求
    try {
      xhr.send(data ? (typeof data === 'string' ? data : JSON.stringify(data)) : null);
    } catch (e) {
      reject(new Error(`Failed to send request: ${e.message}`));
    }
  });
}

// 使用示例
// GET 请求
request({
  url: 'https://jsonplaceholder.typicode.com/posts/1',
  method: 'GET'
})
.then(response => console.log('GET Success:', response))
.catch(error => console.error('GET Error:', error));

// POST 请求
request({
  url: 'https://jsonplaceholder.typicode.com/posts',
  method: 'POST',
  data: {
    title: 'foo',
    body: 'bar',
    userId: 1
  },
  headers: {
    'X-Custom-Header': 'value'
  }
})
.then(response => console.log('POST Success:', response))
.catch(error => console.error('POST Error:', error));

// 带超时设置
request({
  url: 'https://jsonplaceholder.typicode.com/posts/1',
  method: 'GET',
  timeout: 5000
})
.then(response => console.log('Timeout Success:', response))
.catch(error => console.error('Timeout Error:', error));
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值