【学习笔记77】ajax的函数封装

一、封装分析

(一 )封装方案

1、回调函数方式

将来使用的时候, 可能会遇到回调地狱

2、promise方式

效果不会有变化, 而且还能和 async/await 一起使用

(二)函数的参数

  1. 请求方式: method => 默认值 get
  2. 请求地址: url => 必填
  3. 同步异步: async => 默认值 true
  4. 请求参数: data => 默认值 ‘’
  5. 请求头: headers => 默认值 {content-type: application/x-www-form-urlencoded}
  6. 解析参数: dataType => 默认值 ‘string’

注意:将以上参数封装成对象(options)的形式更加方便

(三)函数的返回值

  • promise实例化对象
  • 让开发自己使用 .then或者 .catch

二、参数的验证

function ajax(options) {
    // 请求地址: url => 必填,也就是说url不能为undefined
    if (options.url === undefined) {
        throw new Error('您没有传递url,url为必填')
    }

    // 请求方式: method => 默认值get
    // 也就是说method可以是get、post和undefined
    if (!(/^(get|post)$/i.test(options.method) || options.method === undefined)) {
        throw new Error('method目前仅支持post或者get')
    }

    // 同步异步: async => 默认值true
    // 也就是说 async可以为true,false和undefined
    if (!(options.async === undefined || typeof (options.async) === 'boolean')) {
        throw new Error('async目前仅支持true或false')
    }

    // 请求参数: data => 默认值 ''
    // 参数data可以是字符串、对象和undefined
    const optionsDataType = Object.prototype.toString.call('options.data');
    if (!(
        optionsDataType === "[object Object]" ||
        optionsDataType === "[object String]" ||
        optionsDataType === "[object Undefined]"
    )) throw new Error('data目前仅支持字符或对象')

    // 请求头: headers => 默认值 {content-type: application/x-www-form-urlencoded}
    // headers可以时候undefined,也可以是对象
    const headersType = Object.prototype.toString.call(options.headers)
    if(!(headersType === '[object Undefined]' || headersType === '[object Object]')){
        throw new Error('headers暂时仅支持对象格式')
    }
    
    // 解析参数: dataType => 默认值 'string'
    // dataType参数可以是undefined、'string'和'json'
    if(options.dataType === undefined || /^(string|json)$/.test(options.dataType)){
        throw new Error('dataType目前净资产string和JSON')
    }
    console.log(options);
}

ajax({
    url: 'http://localhost:8888',
    data: 'key=value',
    method: 'get',
    async: true,
    headers: {
        'content-type': 'application/x-www-form-urlencoded'
    },
    dataType: ''
})

在这里插入图片描述

验证:当我们不传url时

ajax({
    data: 'key=value',
    method: 'get',
    async: true,
    headers: {
        'content-type': 'application/x-www-form-urlencoded'
    },
    dataType: ''
})

在这里插入图片描述

三、处理默认参数

1、补充知识点

  • ??:空值运算符
  • 作用:符号左边是undefined或者null,会运行符号右边

2、封装函数处理data对象

function objToStr(obj){
    let str = '';
    for(let key in obj){
        str += `${key}=${obj[key]}&`;
    }
    str = str.slice(0, str.length-1);
    return str;
}

3、结构解析

	let obj1 = {
	    a: 1,
	    b: 2
	}
	
	let obj2 ={
	    c: 3,
	    d: 4,
	    ...obj1
}
console.log(obj2);

在这里插入图片描述

4、处理默认参数

  • 继续在ajax函数里面书写
    // 默认传输的处理
    const _options = {
        // 代码执行到这个位置 说明url一定传递了
        url: options.url,

        // 代码运行到这里,method要么是undefined,要么是get/post
        method: options.method || 'get',
        // ??空值运算符 符号左边是undefined或者null,会运行符号右边的
        async: options.async ?? true,

        // 代码运行到这里,data可能是对象、字符串和undefined
        data: options.data || '',

        // 代码运行这里 headers可能是undefined或对象
        headers: {
            "content-type": "application/x-www-form-urlencoded",
            ...options.headers,
        },

        // 代码运行到这里 dataType可能是undefined或者字符串
        dataType: options.dataType || 'string',
    }

    // 处理_options.data中对象转化为模板字符串
    if (!(typeof (_options.data) === 'string')) {
        // console.log(_options.data);
        _options.data = objToStr(_options.data)
    }

    console.log('原始对象', options);
    console.log('默认数据', _options);

在这里插入图片描述

四、设置get和post请求头

  • GET请求:不需要content-type,可能需要authorization
  • POST请求:需要content-type,可能需要authorization
    // 如果当前是get请求 在路径后拼接参数
    if (/^grt$/i.test(_options.method)) {
        _options.url = options.url + '?' + _options.data
    }

    // 发送请求
    const p = new Promise((res, rej) => {
        const xhr = new XMLHttpRequest();
        xhr.open(_options.method, _options.url, _options.async);
        xhr.onload = function () {
            // 代码运行到这里 dataType要么是string,要么是JSON
            if (_options.dataType === 'string') {
                res(xhr.responseText);
            } else {
                res(JSON.parse(xhr.responseText))
            }
        };

        // 对post请求认证的处理
        if (/^post$/i.test(_options.method)) {
            xhr.setRequestHeader('content-type', _options.headers["content-type"])
        }

        if (_options.headers.authorization) {
            xhr.setRequestHeader('authorization', _options.headers.authorization)
        }

        // 如果当前是post请求,那么send内部需要添加参数 否则不需要
        /^POST$/i.test(_options.method) ? xhr.send(_options.data) : xhr.send();
    })
    return p;

五、完整代码

function objToStr(obj) {
    let str = "";
    for (let k in obj) {
        str += `${k}=${obj[k]}&`;
    }
    str = str.slice(0, str.length - 1);
    return str;
}
function createAjax(url) {
    let baseUrl = url;

    function ajax(options) {
        if (options.url === undefined) {
            throw new Error("您没有传递 url, url 为 必传");
        }

        if (
            !(
                /^(GET|POST)$/i.test(options.method) ||
                options.method === undefined
            )
        ) {
            throw new Error("method 目前仅支持 post 或者 get");
        }

        if (
            !(options.async === undefined || typeof options.async === "boolean")
        ) {
            throw new Error("async 目前仅支持 ture 或者 false");
        }

        const optionsDataType = Object.prototype.toString.call(options.data);
        if (
            !(
                optionsDataType === "[object Object]" ||
                optionsDataType === "[object String]" ||
                optionsDataType === "[object Undefined]"
            )
        ) {
            throw new Error("data 目前仅支持 字符串或者 对象");
        }

        const headersType = Object.prototype.toString.call(options.headers);
        if (
            !(
                headersType === "[object Undefined]" ||
                headersType === "[object Object]"
            )
        ) {
            throw new Error("header 暂时仅支持 对象格式");
        }

        if (
            !(
                options.dataType === undefined ||
                /^(string|json)$/.test(options.dataType)
            )
        ) {
            throw new Error("dataType 目前仅支持 'string' 或者 'json'");
        }

        const _options = {
            url: baseUrl + options.url,
            method: options.method || "GET",
            async: options.async ?? true,
            data: options.data || "",
            headers: {
                "content-type": "application/x-www-form-urlencoded",
                ...options.headers,
            },
            dataType: options.dataType || "string",
        };

        if (!(typeof _options.data === "string")) {
            _options.data = objToStr(_options.data);
        }

        if (/^GET$/i.test(_options.method)) {
            _options.url = _options.url + "?" + _options.data;
        }

        const p = new Promise(function (res, rej) {
            const xhr = new XMLHttpRequest();
            xhr.open(_options.method, _options.url, _options.async);
            xhr.onload = function () {
                try {
                    if (_options.dataType === "string") {
                        res({
                            code: 1,
                            info: xhr.responseText,
                        });
                    } else {
                        res({
                            code: 1,
                            info: JSON.parse(xhr.responseText),
                        });
                    }
                } catch (error) {
                    res({
                        code: 0,
                        info: xhr.responseText,
                    });
                }
            };

            if (/^POST$/i.test(_options.method)) {
                xhr.setRequestHeader(
                    "content-type",
                    _options.headers["content-type"]
                );
            }

            if (_options.headers.authorization) {
                xhr.setRequestHeader(
                    "authorization",
                    _options.headers.authorization
                );
            }
            /^POST$/i.test(_options.method)
                ? xhr.send(_options.data)
                : xhr.send();
        });

        return p;
    }

    return ajax;
}

const ajax = createAjax(confg.baseUrl);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值