ajax入门

109 阅读8分钟

1.前后端交互

其实就是一个前后端通讯, 是我们在开发中, 必不可少的一个技能

目前我们用到的技术就是 ajax

流程为 在前端开发中, 在某一个时刻(页面首次打开渲染的时候, 或者点击下一页需要新的数据的时候)

此时通过 ajax 向后端(服务端)发送一个请求, 拿到 所谓的数据

发送请求需要传一些参数(就是告诉后端你要什么东西), 如果你不知道, 那么问你的组长要一个 '接口文档'

2.实现一个 ajax 请求

         // 1. 创建一个 ajax 对象
        const xhr = new XMLHttpRequest()

        // 2. 配置 ajax 对象
        // xhr.open('请求的方式(不区分大小写)', '请求的地址', '一个布尔值')
        xhr.open('GET', 'http://localhost:8888/test/first', true)

        // 3. 发送请求
        xhr.send()

        // 4. 接收响应
        xhr.onload = function () {
            // console.log('现在后端已经给我们返回了 我们想要的数据了')
            console.log(xhr.responseText)   // 哇塞, 你已经成功使用 ajax 发送给我了一个请求, 这是我给你的回应, 我是一个字符串类型 ^_^ !
        }

3.ajax 的异步问题

ajax 是否异步为 第二步配置的第三个参数决定的, 也就是那个布尔值

默认为 true 代表的是开启异步, 如果传递的是 false 代表关闭异步开启同步

同步和异步的差别

    1. 创建一个 ajax 对象 (同步代码)
    1. 配置对象 (同步代码, 但是第三个参数决定了 下一步是否为异步)
    1. 发送请求 (根据上一步的配置, 才能看出是否为异步)
    1. 接受响应 (同步代码)

如果传递的是 true 或者没有传递, 那么为异步, 此时的运行流程

    1. 创建一个对象
    1. 配置对象
    1. 发送请求
    1. 接收响应
    1. 响应完成了

如果传递的是 false, 那么为同步, 此时的运行流程

    1. 创建一个对象
    1. 配置对象
    1. 发送一个请求, 等待请求完成后, 开始执行后边的代码
    1. 接收响应 (前边三步已经把这个请求完全的运行结束了, 所以此时不可能再触发这个函数了)

如果传递的是 false, 那么为同步, 此时的运行流程

    1. 创建一个对象
    1. 配置对象
    1. 接收响应, 等到请求完成的时候, 会触发
    1. 发送一个请求, 等待请求完成后, 开始执行后边的代码

如果传递是异步, 可以按照 1234的流程书写(1243也可以)

如果传递的是同步, 必须按照 1243 的流程书写

所以在开发的时候, 为了方便起见, 一般都会书写为 1243

        // 1. 创建一个 ajax 对象
        const xhr = new XMLHttpRequest()

        // 2. 配置 ajax 对象
        xhr.open('GET', 'http://localhost:8888/test/first', false)

        // 4. 接收响应
        xhr.onload = function () {
            // console.log('现在后端已经给我们返回了 我们想要的数据了')
            console.log(xhr.responseText)   // 哇塞, 你已经成功使用 ajax 发送给我了一个请求, 这是我给你的回应, 我是一个字符串类型 ^_^ !
        }

        // 3. 发送请求
        xhr.send()

4.http 传输协议

还有一个协议 https, 相对于 http 安全一点点

根据传输协议规定, 必须是由前端向后端发送请求, 发送请求的时候如果要携带一些参数, 必须是字符串格式

    1. 建立连接
    • 浏览器和服务端 建立一个连接
    1. 发送请求
      • 要求前端必须以 '请求报文' 的形式发送;
      • 请求报文 由 浏览器进行组装, 我们只需要提供对应的信息即可;
      • 比如说: 请求的方式, 请求的地址, 请求需要的参数
    1. 接收响应
      • 要求后端必须以 '响应报文' 的形式返回;
      • 响应报文内有一个东西叫做响应状态码;
    1. 断开连接
      • 浏览器和服务端的连接断开

响应状态码

  • 100~199 表明连接还在继续
  • 200~299 表明连接各种成功 但现在只会返回一个 200
  • 300~399 表明请求重定向
  • 400~499 表明请求失败 但现在只会看到一些 403 404 401 400 一般4开头是前端的问题
  • 500~599 表明服务端出错 跟前端无关, 是后端的问题

5.ajax 的状态码

通过一个数字, 表明 ajax 当前运行到那一步了

  • 0: ajax 创建成功
  • 1: 当前 ajax 配置成功
  • 2: 当前 ajax 发送成功
  • 3: 当前 浏览器 正在解析服务端返回给我们的内容
    • 如果返回的内容少, 这一步基本能接受完
    • 如果返回的内容多, 这一步接收的是不完整的
  • 4: 表明 浏览器 已经把服务端返回的内容 全都解析完毕了~
        // 1. 创建一个 ajax 对象
        const xhr = new XMLHttpRequest()
        // console.log(xhr.readyState) // 0

        // 2. 配置 ajax 对象
        xhr.open('GET', 'http://localhost:8888/test/first')
        // console.log(xhr.readyState) // 1

        // 4. 配置接收响应的函数
        // xhr.onload = function () {
        //     console.log(xhr.responseText)
        // }

        // 3. 发送请求
        xhr.send()

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                console.log('当前浏览器已经完全解析完毕 返回的数据', xhr.responseText)
            }
        }

        // xhr.onreadystatechange = function () {
        //     if (xhr.readyState === 2) {
        //         console.log('当前 请求 发送成功', xhr.responseText)
        //     } else if (xhr.readyState === 3) {
        //         console.log('当前浏览器正在解析返回的数据, 可能没完成', xhr.responseText)
        //     } else if (xhr.readyState === 4) {
        //         console.log('当前浏览器已经完全解析完毕 返回的数据', xhr.responseText)
        //     }
        // }

6.请求方式的区别

  • get 偏向于获取的语义 (商品列表数据, 用户详情, 商品详情)
    • elete 偏向于获取的语义 (删除某一个内容)
  • post 偏向于修改的语义 (修改用户名, 修改密码)
    • put 偏向于修改的语义 (修改库存, 修改收藏数量)
    • 等等..... 现在 市面公司中常用的方式只有两个, get/post

请求方式不同, 会导致传参的方式不同, 除此之外对我们前端来说没有区别

  • get: 直接将需要传递参数拼接在路径后即可, 注意使用 ? 间隔
    • http://localhost:8888/test/first?key=value
    • http://localhost:8888/test/first?key=value&key2=value2
  • post: 也是需要传递字符串, 只不过不在放在 地址路径后, 而是放在 请求体内书写(其实就是 xhr.send())

    • 在传参的时候还需要配置一个请求头中的属性 content-type
    • content-type 赋值的时候, 还要区分我们传递的是普通字符串, 还是 json 格式的字符串
    • 普通字符串: xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
    • json字符串: xhr.setRequestHeader('content-type', 'application/json')

7.测试请求

        //测试请求2
        // 1. 创建一个 ajax 对象
        const xhr = new XMLHttpRequest()
        // 2. 配置 ajax 对象 xhr.open('请求方式', '请求地址')
        xhr.open('GET', 'http://localhost:8888/test/second')
        // 4. 配置接收响应的函数
        xhr.onload = function () {
            const res = JSON.parse(xhr.responseText)
            console.log(res)
        }
        // 3. 发送请求
        xhr.send()
        
        //测试请求3
        //1. 创建一个 ajax 对象
        const xhr = new XMLHttpRequest()
        // 2. 配置 ajax 对象 xhr.open('请求方式', '请求地址')
        xhr.open('GET', 'http://localhost:8888/test/third?name=zhangsan&age=18')
        // 4. 配置接收响应的函数
        xhr.onload = function () {
            const res = JSON.parse(xhr.responseText)
            console.log(res)
        }
        // 3. 发送请求
        xhr.send()

        // 测试请求4

        /**
         *  application/x-www-form-urlencoded 这是 post 格式的传参是需要给 content-type 配置的属性值
         *      这样传递表明需要的是 普通字符串
         * 
         *  如果是 json 格式的字符串, 需要传递为 application/json
        */

        const xhr = new XMLHttpRequest()
        // 2. 配置 ajax 对象 xhr.open('请求方式', '请求地址')
        xhr.open('POST', 'http://localhost:8888/test/fourth')
        // 4. 配置接收响应的函数
        xhr.onload = function () {
            const res = JSON.parse(xhr.responseText)
            console.log(res)
        }

        // 3.1 post 请求传参时需要配置 content-type(请求头内的属性)
        xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')

        // 3.2 发送请求
        xhr.send('name=张三&age=18')

8.封装 ajax

  • 参数:
      1. 请求的方式: 选填, 默认值为 GET; 形参名: type
      1. 请求的地址: 必填; 形参名: url
      1. 请求为同步还是异步: 选填, 默认值为 true; 形参名: async
      1. 请求需要携带参数: 选填, 默认为 ''; 形参名: data
  • 返回值:
    • 需要返回一个 promise 对象, 后续可以通过 .then 或者 async/await 去使用
         // function myAjax(type = 'GET', url, async = true, data = '') {}
        // myAjax('POST', 'http:xxx', false, 'name=zhangsan')
        // myAjax('http:xxx', false, 'name=zhangsan')

        // function myAjax(url, type = 'GET', async = true, data = '') { }
        // myAjax('http:xxx', 'POST', false)

        function myAjax(options) { }
        myAjax({
            url: 'http:xxx',
            async: false,
            data: 'name=zhangsan'
        })
        function myAjax(options) {
            // 1. 验证 参数中的 url 必传
            if (options.url === undefined) throw new Error('参数中缺少必传项 url')  // 返回一个错误

            // 1.1 参数格式验证, 拿请求方式举例: type 只接受 undefined 或者 string 两种类型
            if (!(options.type === undefined || typeof(options.type) === 'string')) throw new Error('参数中 type 的类型必须为 string')

            // 1.2 补全剩余参数的格式校验

            // 2. 封装默认值
            const _options = {
                url: options.url,
                type: options.type || 'GET',
                data: options.data || '',
                // 空值检测符, 该符号的特点 只会在 左侧的值为空值的时候返回右侧, 比如左侧为: null, undefined
                async: options.async ?? true
            }

            // 请求的参数还没处理, 后续需要继续完善
            const xhr = new XMLHttpRequest()
            xhr.open(_options.type, _options.url, _options.async)
            xhr.onload = function () {
                console.log(xhr.responseText)
            }
            xhr.send()
        }

        myAjax({
            url: 'http://localhost:8888/test/first',
        })