【仿旅游网站】Ajax封装

结合class和模块化

“ajax封装”目录

ajax.js (Ajax类)

// 工具函数
import { serialize, addURLData, serializeJSON } from './utils.js';

// 默认参数
import DEFAULTS from '.defaults.js'

class Ajax{
  constructor(url, options){
    // options分用户参数、默认参数
    this.url = url;
    this.options = Object.assign({}, DEFAULTS, options);
    
    // 初始化
    this.init();
  }
  // 初始化
  init() {
    const xhr = new XMLHttpRequest();
    this.xhr = xhr;
    
    // 绑定响应事件处理程序
    this.bindEvents();

    this.xhr.open(this.options.method, this.url+this.addParam(), true); // true表示异步 

    // 设置 responseType
    this.setResponseType();
    
    // 设置跨域是否携带 cookie
    this.setCookie();
    
    // 设置超时
    this.setTimeout();
    
    // 发送请求
    this.sendData();
  }
  
  // 与事件处理有关的都放进来,绑定响应事件处理程序
  bindEvents(){
    const xhr = this.xhr;
    const (success, httpCodeError, error, abort, timeout) = this.options;
    // load
    xhr.addEventListener(
      'load',
      () => {
        if (this.ok()) {
          success(xhr.response, xhr);
        } else {
          httpCodeError(xhr.status, xhr);
        }
      },
      false
    );   
    
    // error
    // 当请求遇到错误时,将触发 error 事件
    xhr.addEventListener(
      'error',
      () => {
        error(xhr);
      },
      false
    );

    // abort
    xhr.addEventListener(
      'abort',
      () => {
        abort(xhr);
      },
      false
    );

    // timeout
    xhr.addEventListener(
      'timeout',
      () => {
        timeout(xhr);
      },
      false
    );
  }
  // 检测响应的 HTTP 状态码是否正常
  ok() {
    const xhr = this.xhr;
    return (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304;
  }

  // 在地址上添加数据
  addParam() {
    const { params } = this.options;

    if (!params) return '';
    // 有时候url上面已经带参数,即?words=js;有时候不带参数,要先加?
    return addURLData(this.url, serialize(params));
  }
  
  // 设置 responseType
  setResponseType() {
    this.xhr.responseType = this.options.responseType;
  }
  // 设置跨域是否携带 cookie
  setCookie() {
    if (this.options.withCredentials) {
      this.xhr.withCredentials = true;
    }
  }
  
  // 设置超时
  setTimeout() {
    const { timeoutTime } = this.options;

    if (timeoutTime > 0) {
      this.xhr.timeout = timeoutTime;
    }
  }
  // 发送请求
  sendData() {
    const xhr = this.xhr;

    if (!this.isSendData()) {
      return xhr.send(null);
    }

    let resultData = null;
    const { data } = this.options;

    // 发送 FormData 格式的数据
    if (this.isFormData()) {
      resultData = data;
    } else if (this.isFormURLEncodedData()) {
      // 发送 application/x-www-form-urlencoded 格式的数据

      this.setContentType(CONTENT_TYPE_FORM_URLENCODED);
      resultData = serialize(data);
    } else if (this.isJSONData()) {
      // 发送 application/json 格式的数据

      this.setContentType(CONTENT_TYPE_JSON);
      resultData = serializeJSON(data);
    } else {
      // 发送其他格式的数据

      this.setContentType();
      resultData = data;
    }

    xhr.send(resultData);
  }
  // 是否需要使用 send 发送数据
  isSendData() {
    const { data, method } = this.options;

    if (!data) return false;

    if (method.toLowerCase() === HTTP_GET.toLowerCase()) return false;

    return true;
  }
  // 是否发送 FormData 格式的数据
  isFormData() {
    return this.options.data instanceof FormData;
  }
  // 是否发送 application/x-www-form-urlencoded 格式的数据
  isFormURLEncodedData() {
    return this.options.contentType
      .toLowerCase()
      .includes(CONTENT_TYPE_FORM_URLENCODED);
  }
  // 是否发送 application/json 格式的数据
  isJSONData() {
    return this.options.contentType.toLowerCase().includes(CONTENT_TYPE_JSON);
  }

  // 设置 Content-Type
  setContentType(contentType = this.options.contentType) {
    if (!contentType) return;

    this.xhr.setRequestHeader('Content-Type', contentType);
  }

  // 获取 XHR 对象
  getXHR() {
    return this.xhr;
  }
}

export default Ajax;

default.js (存放默认参数 )

// 默认参数
const DEFAULTS = {
  method: 'GET',
  // 请求头携带的数据
  params: null,
  //params: {
  //  username: 'jinhuai',
  //  age: '22'
  //}
  // username=jinhuai&age=22
  // 请求体携带的数据
  data: null,
  //data: {
  //  username: 'jinhuai',
  //  age: '22'
  //}
  // data: FormData数据
  contentType: 'application/x-www-form-urlencoded',
  responseType:'',  //默认文本
  timeoutTime: 0,  // 默认没有超时时间
  withCredentials: false,

  // 方法
  success(){},
  httpCodeError(){},
  error(){},
  abort(){},
  timeout(){}
};

export default DEFAULTS;

utils.js (工具函数)

const serialize = param => {
  const results = 
  for(const [key, value] of Object.entries(param)){
    results.push(`${encodeURLComponent(key)}=${encodeURLComponent(value)}`);
  }
  // ['username=jinhuai', 'age=22'];
  return results.join('&');
}

// 数据序列化成 JSON 格式的字符串
const serializeJSON = param => {
  return JSON.stringify(param);
};

// 给 URL 添加参数
// www.imooc.com?words=js&
const addURLData = (url, data) => {
  if (!data) return '';

  const mark = url.includes('?') ? '&' : '?';

  return `${mark}${data}`;
};

export { serialize, addURLData, serializeJSON };


constants.js

// 常量
export const HTTP_GET = 'GET';
export const CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded';
export const CONTENT_TYPE_JSON = 'application/json';


index.js

import Ajax from './ajax.js';

const ajax = (url, options) => {
  return new Ajax(url, options).getXHR();
};

const get = (url, options) => {
  return ajax(url, { ...options, method: 'GET' });
};

const getJSON = (url, options) => {
  return ajax(url, { ...options, method: 'GET', responseType: 'json' });
};

const post = (url, options) => {
  return ajax(url, { ...options, method: 'POST' });
};

export { ajax, get, getJSON, post };

导入

<script type="module">
import { ajax, get, getJSON, post } from './ajax/index.js';

const url = 'https://www.imooc.com/api/http/search/suggest?words=js';
// const url = 'https://www.iimooc.com/api/http/search/suggest?words=js';

// const url = './414.html';

const xhr = ajax(url, {
  method: 'GET',
  params: { username: 'alex' },
  data: {
    age: 18
  },
  responseType: 'json',
  // timeoutTime: 10,

  success(response) {
    console.log(response);
  },
  httpCodeError(err) {
    console.log('http code error', err);
  },
  error(xhr) {
    console.log('error', xhr);
  },
  abort(xhr) {
    console.log('abort', xhr);
  },
  timeout(xhr) {
    console.log('timeout', xhr);
  }
});

xhr.abort();
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值