• 【学习笔记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: ''
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    在这里插入图片描述

    验证:当我们不传url时

    ajax({
        data: 'key=value',
        method: 'get',
        async: true,
        headers: {
            'content-type': 'application/x-www-form-urlencoded'
        },
        dataType: ''
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    三、处理默认参数

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、结构解析

    	let obj1 = {
    	    a: 1,
    	    b: 2
    	}
    	
    	let obj2 ={
    	    c: 3,
    	    d: 4,
    	    ...obj1
    }
    console.log(obj2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    四、设置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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    五、完整代码

    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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
  • 相关阅读:
    【UniApp】-uni-app-CompositionAPI应用生命周期和页面生命周期
    使用 TinyEngine 低代码引擎实现三方物料集成
    快速搭建springcloud项目
    第10届蓝桥杯Scratch国赛真题集锦
    Vuex源码解析
    原型网络Prototypical Network的python代码逐行解释,新手小白也可学会!!-----系列4
    基于open CV实现YOLOv3复现_预测阶段和后处理阶段
    【腾讯云原生降本增效大讲堂】作业帮云原生降本增效实践之路
    6.7-7.2 读书笔记
    JUC并发编程(5)(自定义线程池 + 共享模型之工具2)
  • 原文地址:https://blog.csdn.net/m0_58190023/article/details/128161237