专栏首页小康的自留地三、基于promise封装属于自己的Ajax库

三、基于promise封装属于自己的Ajax库

分析

实现一个自己的ajax库,那么我们需要有一些配置,用于修改baseURLurl等信息。

let _default = {
    method: "GET",
    url: "",
    baseURL: "",
    headers: {},
    dataType: "JSON",
    data: null, // => post系列请求
    params: null, // => get系列请求基于?传参
    cache: true,
};

接下来便是核心函数,核心函数内处理数据,并且发出请求。

(function anonymous() {
    let ajaxPromise = function ajaxPromise(options) {
        let {
            method,
            url,
            baseURL,
            headers,
            dataType,
            data,
            params,
            cache,
        } = options;
       // 处理参数
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            // URL地址
            xhr.open(method, `${baseURL}${url}`);
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (/^2|3\d{2}/.test(xhr.status)) {
                        // 如果请求成功,则返回结果
                        resolve(result);
                        return;
                    }
                    // 请求失败抛出异常
                    reject(xhr.status);
                }
            };
            // 发送的数据
            xhr.send(data);
        });
    };
}

最重要的就是发送数据前对传入数据的处理。首先判断根据请求方式处理需要传入的参数。

(function anonymous() {
    let ajaxPromise = function ajaxPromise(options) {
        let {
            method,
            url,
            baseURL,
            headers,
            dataType,
            data,
            params,
            cache,
        } = options;
        // 处理参数
        if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)) {
            //   GET系列
            if (params) {
                url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`;
            }
            if (cache === false) {
                url += `${ajaxPromise.check(url)}_=${+new Date()}`;
            }
            data = null;
        } else {
            //   POST系列
            if (data) {
                data = ajaxPromise.formatData(data);
            }
        }
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            // URL地址
            xhr.open(method, `${baseURL}${url}`);
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (/^2|3\d{2}/.test(xhr.status)) {
                        // 如果请求成功,则返回结果
                        resolve(result);
                        return;
                    }
                    // 请求失败抛出异常
                    reject(xhr.status);
                }
            };
            // 发送的数据
            xhr.send(data);
        });
    };
    // 将对象变成urlencoded字符串
    ajaxPromise.formatData = function formatData(obj) {
        let str = ``;
        for (let attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                str += `${attr}=${obj[attr]}&`;
            }
        }
        return str.substring(0, str.length - 1);
    };
    ajaxPromise.defaults = _default;
}

接下来处理的是发出请求时,请求头的一些配置

(function anonymous() {
    let ajaxPromise = function ajaxPromise(options) {
        let {
            method,
            url,
            baseURL,
            headers,
            dataType,
            data,
            params,
            cache,
        } = options;
        // 处理参数
        if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)) {
            //   GET系列
            if (params) {
                url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`;
            }
            if (cache === false) {
                url += `${ajaxPromise.check(url)}_=${+new Date()}`;
            }
            data = null;
        } else {
            //   POST系列
            if (data) {
                data = ajaxPromise.formatData(data);
            }
        }
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            // URL地址
            xhr.open(method, `${baseURL}${url}`);
            if (headers !== null && typeof headers === "object") {
                for (let attr in headers) {
                    if (headers.hasOwnProperty(attr)) {
                        //   处理中文
                        let val = headers[attr];
                        if (/[\u4e00-\u9fa5]/.test(val)) {
                            // 将中文进行编码
                            val = encodeURIComponent(val);
                        }
                        xhr.setRequestHeader(attr, headers[attr]);
                    }
                }
            }
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (/^2|3\d{2}/.test(xhr.status)) {
                        // 如果请求成功,则返回结果
                        resolve(result);
                        return;
                    }
                    // 请求失败抛出异常
                    reject(xhr.status);
                }
            };
            // 发送的数据
            xhr.send(data);
        });
    };
    // 将对象变成urlencoded字符串
    ajaxPromise.formatData = function formatData(obj) {
        let str = ``;
        for (let attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                str += `${attr}=${obj[attr]}&`;
            }
        }
        return str.substring(0, str.length - 1);
    };
    ajaxPromise.defaults = _default;
}

在然后就是处理当请求发出去,将结果进行返回

(function anonymous() {
    let ajaxPromise = function ajaxPromise(options) {
        let {
            method,
            url,
            baseURL,
            headers,
            dataType,
            data,
            params,
            cache,
        } = options;
        // 处理参数
        if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)) {
            //   GET系列
            if (params) {
                url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`;
            }
            if (cache === false) {
                url += `${ajaxPromise.check(url)}_=${+new Date()}`;
            }
            data = null;
        } else {
            //   POST系列
            if (data) {
                data = ajaxPromise.formatData(data);
            }
        }
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            // URL地址
            xhr.open(method, `${baseURL}${url}`);
            if (headers !== null && typeof headers === "object") {
                for (let attr in headers) {
                    if (headers.hasOwnProperty(attr)) {
                        //   处理中文
                        let val = headers[attr];
                        if (/[\u4e00-\u9fa5]/.test(val)) {
                            // 将中文进行编码
                            val = encodeURIComponent(val);
                        }
                        xhr.setRequestHeader(attr, headers[attr]);
                    }
                }
            }
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (/^2|3\d{2}/.test(xhr.status)) {
                        let result = xhr.responseText;
                        dataType.toUpperCase();
                        dataType === "JSON"
                            ? (result = JSON.parse(result))
                        : dataType === "XML"
                            ? (result = xhr.responseXML)
                        : null;
                        resolve(result);
                        return;
                    }
                    reject(xhr.status);
                }
            };
            // 发送的数据
            xhr.send(data);
        });
    };
    // 将对象变成urlencoded字符串
    ajaxPromise.formatData = function formatData(obj) {
        let str = ``;
        for (let attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                str += `${attr}=${obj[attr]}&`;
            }
        }
        return str.substring(0, str.length - 1);
    };
    ajaxPromise.defaults = _default;
}

最后,只需要将方法暴露即可。

(function anonymous() {
  let _default = {
    method: "GET",
    url: "",
    baseURL: "",
    headers: {},
    dataType: "JSON",
    data: null, // => post系列请求
    params: null, // => get系列请求基于?传参
    cache: true,
  };
  let ajaxPromise = function ajaxPromise(options) {
    let {
      method,
      url,
      baseURL,
      headers,
      dataType,
      data,
      params,
      cache,
    } = options;
    //   处理参数
    if (/^(GET|DELETE|HEAD|OPTIONS)$/i.test(method)) {
      //   GET系列
      if (params) {
        url += `${ajaxPromise.check(url)}${ajaxPromise.formatData(params)}`;
      }
      if (cache === false) {
        url += `${ajaxPromise.check(url)}_=${+new Date()}`;
      }
      data = null;
    } else {
      //   POST系列
      if (data) {
        data = ajaxPromise.formatData(data);
      }
    }
    return new Promise((resolve, reject) => {
      let xhr = new XMLHttpRequest();
      xhr.open(method, `${baseURL}${url}`);
      if (headers !== null && typeof headers === "object") {
        for (let attr in headers) {
          if (headers.hasOwnProperty(attr)) {
            //   处理中文
            let val = headers[attr];
            if (/[\u4e00-\u9fa5]/.test(val)) {
              // 将中文进行编码
              val = encodeURIComponent(val);
            }
            xhr.setRequestHeader(attr, headers[attr]);
          }
        }
      }
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
          if (/^2|3\d{2}/.test(xhr.status)) {
            let result = xhr.responseText;
            dataType.toUpperCase();
            dataType === "JSON"
              ? (result = JSON.parse(result))
              : dataType === "XML"
              ? (result = xhr.responseXML)
              : null;
            resolve(result);
            return;
          }
          reject(xhr.status);
        }
      };
      xhr.send(data);
    });
  };
  // 将对象变成urlencoded字符串
  ajaxPromise.formatData = function formatData(obj) {
    let str = ``;
    for (let attr in obj) {
      if (obj.hasOwnProperty(attr)) {
        str += `${attr}=${obj[attr]}&`;
      }
    }
    return str.substring(0, str.length - 1);
  };
  ajaxPromise.defaults = _default;
  ajaxPromise.check = function check(url) {
    return url.indexOf("?") < -1 ? "&" : "?";
  };
  // => get
  ["get", "delete", "head", "options"].forEach((item) => {
    ajaxPromise[item] = function anonymous(url, options = {}) {
      options = {
        ..._default, // => 默认值或者基于defaults修改的值
        ...options, // => 用户调取方法传递的配置项
        url: url, // => 请求的url地址(第一个参数:默认配置项和传递的配置项不会出现url)
        method: item.toUpperCase(),
      };
      return ajaxPromise(options);
    };
  });

  // => POST
  ["post", "put", "patch"].forEach((item) => {
    ajaxPromise[item] = function anonymous(url, data = {}, options = {}) {
      options = {
        ..._default,
        ...options,
        url: url,
        method: item.toUpperCase(),
        data: data,
      };
      return ajaxPromise(options);
    };
  });

  ajaxPromise.post = function (url, data, options) {};
  window.ajaxPromise = ajaxPromise;
})(window);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 三次握手与四次断开

    TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如ip地址...

    Dreamy.TZK
  • 二、jQuery核心函数和工具方法

    jQuery的核心函数就是$();,圆括号内可以传递函数、字符串选择器、字符串代码片段、DOM元素等。

    Dreamy.TZK
  • 十、promise的使用

    Promise对象是一个构造函数,用来生成Promise实例。Promise构造函数接收一个函数作为参数。这个参数的函数又有两个参数,这两个参数分别是resol...

    Dreamy.TZK
  • 前端-Iterator:访问数据集合的统一接口

    遍历器 Iterator是 ES6 为访问数据集合提供的统一接口。任何内部部署了遍历器接口的数据集合,对于用户来说,都可以使用相同方式获取到相应的数据结构。如果...

    grain先森
  • TypeScript入门笔记(二):数据类型

    为了使编写的代码更规范,更有利于维护,增加了类型校验,写 ts 代码必须指定类型。typescript中除了es5中的常见数据类型之外还多了元组类型tuple、...

    王小婷
  • JS面试押题(20190803)

    这周跟大家分享的面试题是“数组去重”。这种题目是个正经一点的厂一般在初试的时候都会让你做到的,频率相当高。曾经统计过差不多有8种不带重复的去重方法,但由于当时数...

    丰臣正一
  • 机器学习实习面经分享(蚂蚁金服,微信,美国亚马逊,完美)

    完美和微信hr面完之后就给了口头offer,蚂蚁得再等几天 阿里,4场技术面+hr面 一面: 面试官说:聊一聊你的项目/paper吧 我:blabla说一通,问...

    牛客网
  • 嘿,这些ES9的骚操作你还不知道吗?

    所有整理的文章都收录到我《Cute-JavaScript》系列文章中,访问地址:http://js.pingan8787.com

    ConardLi
  • 重温基础:ES9系列

    所有整理的文章都收录到我《Cute-JavaScript》系列文章中,访问地址:http://js.pingan8787.com

    用户1462769
  • ES6数组复制

    前面我们了解了...中可以获取未指定的函数,name这里在数组中也可以进行数组的复制

    十月梦想

扫码关注云+社区

领取腾讯云代金券