Ajax请求

150 阅读4分钟

什么是Ajax

  • AJAX (Asynchronous JavaScript And XML(异步的 JavaScript 和 XML)
  • AJAX 不是一种新的语言,而是使用 JavaScript 和 XML ( JSON ) 实现的一种新的技术

想要使用ajax向服务端请求数据,一定要开启服务器!!!

  • 语法:

    • const xhr =new XMLHttpRequest() 创建一个ajax对象
    • xhr.open('请求方式', '请求地址',true) 默认为true,表示异步任务,可以不传
    • xhr.send() 发送请求
    • xhr.onload = function () {console.log(xhr.responseText)} 监听请求完成时间
    • 设置请求头
      • xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
      • xhr.setRequestHeader('content-type','application/JSON')
      • xhr.setRequestHeader('authorization','后端提供给前端的登录凭证')
  • 同步异步

    • ajax有两种执行方式,一般情况下都使用异步方式
    • 使用同步时,不能先发送请求然后监听,要书写相反的顺序
  • http协议

    当前协议规定 请求 只能是 前端发起的, 并且在传输过程中, 只能传递字符串

    • 建立连接:浏览器和服务器建立连接
    • 发送请求:如果需要携带一些参数, 那么需要以请求报文的形式传递,报文由浏览器进行组装, 我们只需要传递一些对应的信息
    • 接收响应:报文由浏览器进行组装, 我们只需要传递一些对应的信息
    • 关闭连接:浏览器和服务器的连接到此结束

    我们的每一个请求都是完全独立的, 前一个请求和后一个请求没有任何关联

  • http请求状态码:(重要)

    • 100~199: 连接正在进行中(持续进行)
    • 200~299: 表明连接成功
    • 300~399: 表明重定向
    • 400~499: 表明前端错误 (没权限/传参错误)
    • 500~599: 表明后端错误
  • ajax状态码

  • 0(未初始化):

    • (XMLHttpRequest)对象已经创建,但还没有调用open()方法。值为0表示对象已经存在,否则浏览器会报错:对象不存在。
  • 1(载入/正在发送请求):

    • 对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true),完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。
  • 2(载入完成/数据接收):

    • 此阶段接收服务器端的响应数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示send()方法执行完成,已经接收完全部响应数据。并为下一阶段对数据解析作好准备。
  • 3(交互/解析数据)正在解析响应内容:

    • 此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。值为3表示正在解析数据。
  • 4 (后台处理完成)响应内容解析完成,可以在客户端调用了:

    • 此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。

请求方式

  • 含义不同
    • get: 表示获取
    • post:表示提交
  • 传参差异
    • 传参方式
      • get:直接拼接在地址的后面就行,格式类似于以前的字符串查询
      • post:在请求体内书写xx.send('在这书写参数')
    • 传参大小
      • get:2kb左右
      • post:原则上没有限制,我们可以在后端添加限制
    • 传参安全
      • get:明文传输,相对不安全
      • post:密文传输。相对安全
    • 传参格式
      • get:传递的是查询字符串格式
      • post:原则上没有限制,但是需要通过content-type 指定传参的格式

封装ajax函数 (需要自取)

    function fn (baseurl) {
        return function myAjax(options) {
        // console.log(options);
    
        // 参数判断
        // 请求地址不能是undefined
        if (options.url === undefined) throw new Error('请求地址不能是undefined')
        // method 可以是get和post,不区分大小写
        const reg = /^(get|post)$/i
        if (!reg.test(options.method) && options.method !== undefined) throw new Error('请传入正确的请求方式')
        // async 可以是undefined 也可以是布尔值
        if (options.async !== undefined && typeof (options.async) !== 'boolean') {
            throw new Error('请传入正确的任务类型')
        }
        // data 可以是undefined 也可以是字符串
        if (
            !(
                options.data === undefined ||
                typeof (options.data) === 'string' ||
                Object.prototype.toString.call(options.data) === '[object Object]'
            )
        ) throw new Error('data传入失败')
        // 设置请求头 可以是undefined 也可以是对象
        if (
            !(
                options.header === undefined ||
                Object.prototype.toString.call(options.header) === '[object Object]'
            )
        ) throw new Error('请求头参数传入失败')
        // 判断解析参数 可以是undefined 和 字符串
        if (
            !(
                options.dataType === undefined ||
                Object.prototype.toString.call(options.dataType) === '[object String]'
            )
        ) throw new Error('解析参数传入失败')
    
    
    
    
        // 参数默认值
        const _options = {
            url: baseurl + options.url,
            method: options.method || 'get',
            async: options.async ?? true,
            data: options.data || '',
            header: {
                'content-type': 'application/x-www-form-urlencoded',
                ...options.header
            },
            dataType: options.dataType || 'JSON'
        }
    
        // 将data转化成查询字符串
        if (Object.prototype.toString.call(_options.data) === '[object Object]') {
            _options.data = setObj(_options.data)
        }
    
        // console.log('传入的参数', options);
        // console.log('默认的参数', _options);
    
        // 设置请求地址
        _options.url = _options.method === 'get' ? `${_options.url}?${_options.data}` : _options.url
        // 封装请求函数
        return new Promise(function (resolve, rejected) {
            const xhr = new XMLHttpRequest()
            xhr.open(_options.method, _options.url, _options.async)
            /**
             *  设置请求头
             *      情况1:header 内有 authorization 的时候
             *      情况2:请求方式 为 post
             *      情况3:send()的参数
            */
            // 情况 1 
            _options.header.authorization && xhr.setRequestHeader('authorization', _options.header.authorization)
            // 情况 2 
            if (/^post$/i.test(_options.method) && _options.data !== '') {
                xhr.setRequestHeader('content-type', _options.header['content-type'])
            }
            // 情况 3 
            /^post$/i.test(_options.method) ? xhr.send(_options.data) : xhr.send();
    
            xhr.onload = function () {
                if (_options.dataType === 'string') {
                    return resolve({
                        code: 1,
                        msg: '请求成功',
                        info: xhr.responseText
                    })
                }
    
                // 转换数据格式
                try {
                    const res = JSON.parse(xhr.responseText)
                    return resolve({
                        code: 1,
                        msg: '请求成功',
                        info: res
                    })
                } catch (error) {
                    return resolve({
                        code: 0,
                        msg: '请求失败',
                        info: error
                    })
                }
            }
        })
    }
}

const myAjax = new fn('http://localhost:8888')


// 将data转化成查询字符串
function setObj(obj) {
    let str = ''
    for (let key in obj) {
        let value = obj[key]
        str += `${key}=${value}&`
    }
    str = str.slice(0, str.length - 1)
    // str = str.slice(0,-1)
    return str
}