Ajax详解(不包括jQuery)

发布时间 2023-05-08 21:28:48作者: 三三要进步

Ajax

URL

URL地址一般由三部分组成

  • 客户端与服务端之间的通信协议
  • 存有该资源的服务器名称
  • 资源在服务器上具体存放位置

0

客户端与服务端通信过程 请求-处理-响应三个步骤

资源请求方式

客户端请求服务器,最常见get和post请求

get请求通常用于获取服务端资源

post请求通常用于向服务端提交数据

Ajax优缺点

优点:可以无需刷新页面而与服务器进行通信

允许你根据用户事件来更新部分页面内容

缺点:没有浏览历史,不能回退

存在跨域问题

SEO不友好

HTTP协议

超文本传输协议

请求报文:

行 POST /xxx HTTP/1.1

头 Host: xx

Cookie: xx

Content-type: xxx

User-Agent: xxx

空行

体 username=admin&password=123

响应报文

行 HTTP/1.1 200 OK

头 Content-type:

Content-length:

Content-encoding:

空行

一个简单页面接收响应数据的程序

页面Ajax

URL

URL地址一般由三部分组成

  • 客户端与服务端之间的通信协议
  • 存有该资源的服务器名称
  • 资源在服务器上具体存放位置

客户端与服务端通信过程 请求-处理-响应三个步骤

资源请求方式

客户端请求服务器,最常见get和post请求

get请求通常用于获取服务端资源

post请求通常用于向服务端提交数据

Ajax优缺点

优点:可以无需刷新页面而与服务器进行通信

允许你根据用户事件来更新部分页面内容

缺点:没有浏览历史,不能回退

存在跨域问题

SEO不友好

HTTP协议

超文本传输协议

请求报文:

行 POST /xxx HTTP/1.1

头 Host: xx

Cookie: xx

Content-type: xxx

User-Agent: xxx

空行

体 username=admin&password=123

响应报文

行 HTTP/1.1 200 OK

头 Content-type:

Content-length:

Content-encoding:

空行

一个简单页面接收响应数据的程序

页面代码

<style>
        #result {
            width: 200px;
            height: 100px;
            border: 1px solid pink;
        }
    </style>
</head>

<body>
    <button>点击</button>
    <div id="result"></div>
</body>
<script>
    const btn = document.querySelector('button')
    const box = document.querySelector('#result')
    btn.onclick = function () {
        const xhr = new XMLHttpRequest()
        //xhr.open() 是 XMLHttpRequest 对象的一个方法,用于初始化一个 HTTP 请求
        //有三个参数,分别是指定请求方法、URL、是否使用异步模式,默认true使用异步模式
        xhr.open('GET', 'http://127.0.0.1:8000/server')
        //xhr.send()会将请求发送给服务器
        xhr.send()
        //onreadystatechange是XMLHttpRequest对象提供的一个事件,当浏览器readyState开始改变就会触发这个事件
        xhr.onreadystatechange = function () {
            //readyState有5个状态值,0, 1, 2, 3, 4,4表示请求已完成
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    // console.log(xhr.status)//状态码
                    // console.log(xhr.statusText)//状态字符串
                    // console.log(xhr.getAllResponseHeaders())//所有响应头
                    // console.log(xhr.response)//响应体
                    box.innerHTML = xhr.response
                }
            }
        }
    }
</script>

js代码(用的Express框架)

//1.引入express
const express = require('express')
//2.创建应用对象
const app = express()
//3.创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
app.get('/server', (request, response) => {
    //设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    //设置响应体
    response.send('Hello Ajax')
})
//4.监听端口启动服务
app.listen(8000, () => {
    console.log("服务器已启动,8000端口监听中...")
})

在Ajax设置url参数

在URL后面加问号参数的形式

xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300')

post请求(和get差别不大,没有贴全部代码)

参数传递方式

xhr.send('a=100&b=200&c=300')

GET和POST区别

两者都是HTTP请求方法

  1. 参数传递方式不同:GET 请求将请求参数拼接在 URL 后面,而 POST 请求则将参数放在请求体中。因此,GET 请求参数可以直接在浏览器地址栏中显示,而 POST 请求参数则不会在地址栏中显示。
  2. 安全性不同:由于 GET 请求参数直接暴露在 URL 中,因此相较而言更不安全。POST 请求将参数放在请求体中,可以保证相对更高的安全性。
  3. 数据类型不同:GET 请求仅支持 ASCII 码字符集,而 POST 请求没有此限制,可以发送二进制数据或其他类型的数据。
  4. 缓存处理不同:GET 请求通常会被浏览器缓存下来,以便下一次访问同样的 URL 时可以更快地响应。POST 请求则不会缓存。
  5. 响应结果不同:GET 请求通常用于获取资源,返回的是资源内容;而 POST 请求通常用于进行数据提交、修改或删除等操作,返回的是操作结果。

服务器响应JSON数据

服务器要返回一个对象,首先要将对象转换为json数据格式,然后客户端接收到这个数据,可以有两种方法来将其响应到页面

  1. 用JSON的parse方法将字符串转换为对象,然后打印其中的属性
  2. XMLHttpRequest对象里面有一个responseType属性,设置为json后会自动将json数据转换为对象,就可以直接使用
	<div></div>
    <script>
        const box = document.querySelector('div')
        window.onkeydown = function () {
            const xhr = new XMLHttpRequest()
            xhr.responseType = 'json'
            xhr.open('get', 'http://127.0.0.1:8000/json-server')
            xhr.send()
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        // console.log(JSON.parse(xhr.response))
                        //可以通过JSON.parse方法把JSON字符串转成对象,再打印属性
                        // const obj = JSON.parse(xhr.response)
                        // box.innerHTML = obj.name
                        // console.log(xhr.response)
                        box.innerHTML = xhr.response.name
                    }
                }
            }
        }
    </script>
//1.引入express
const express = require('express')
//2.创建应用对象
const app = express()
//3.创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
app.get('/server', (request, response) => {
    //设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    //设置响应体
    response.send('Hello Ajax')
})
app.post('/server', (request, response) => {
    //设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    //设置响应体
    response.send('Hello Ajax')
})
app.all('/json-server', (request, response) => {
    //设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    const obj = {
        name: '三三'
    }
    const arr = JSON.stringify(obj)
    //设置响应体
    response.send(arr)
})
//4.监听端口启动服务
app.listen(8000, () => {
    console.log("服务器已启动,8000端口监听中...")
})

解决IE缓存问题

xhr.open('GET','http://127.0.0.1:8000/ie?t='+Date.now())

请求超时网络异常情况

xhr.timeout表示从发送 AJAX 请求到接收响应数据最长等待的时间,如果在该时间内服务器还没有返回响应数据,则会触发 timeout 事件。

	xhr.timeout = 2000
        xhr.ontimeout = function () {
            alert('网络异常,请稍后重试')
        }

取消请求

用到XMLHttpRequest对象中的abort方法

abort方法用于取消当前正在处理的 AJAX 请求。具体来说,当调用该方法时,浏览器会立即中断当前请求,并触发 XMLHttpRequest 对象的 abort 事件。

	<button>点击发送</button>
    <button>点击取消</button>
    <script>
        const btn = document.querySelectorAll('button')
        let xhr = null
        btn[0].addEventListener('click', () => {
            xhr = new XMLHttpRequest()
            xhr.open('GET', 'http://127.0.0.1:8000/delay')
            xhr.send()
        })
        btn[1].addEventListener('click', () => {
            xhr.abort()
        })
    </script>

重复发送请求的问题

设置一个标识变量来判断目前是否正在有请求发送,然后进行取消和发送请求的处理

	<button>发送请求</button>
    <script>
        const btn = document.querySelector('button')
        let xhr = null
        let isSending = false
        btn.addEventListener('click', () => {
            //如果正在发送则取消请求发送一个新的请求
            if (isSending) xhr.abort()
            xhr = new XMLHttpRequest()
            isSending = true
            xhr.open('GET', 'http://127.0.0.1:8000/delay')
            xhr.send()
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    isSending === false
                }
            }
        })
    </script>

axios发送请求

	<button>GET</button>
    <button>POST</button>
    <button>AJAX</button>
    <script>
        const btn = document.querySelectorAll('button')
        //配置baseURL
        axios.defaults.baseURL = 'http://127.0.0.1:8000'
        btn[0].addEventListener('click', () => {
            axios.get('/axios-server', {
                //url参数
                params: {
                    a: 1,
                    b: 2
                },
                headers: {
                    name: 'atguigu',
                    age: 20
                }
            }).then(value => {
                console.log(value)
            })
        })
        btn[1].addEventListener('click', () => {
            //post第二个参数是请求体,第三个参数是其他配置
            axios.post('/axios-server', {
                username: 'admin',
                password: 123
            },
                {
                    //url参数
                    params: {
                        a: 1,
                        b: 2
                    },
                    headers: {
                        name: 'atguigu',
                        age: 20
                    }
                }).then(value => {
                    console.log(value)
                })
        })
        btn[2].addEventListener('click', () => {
            axios({
                //请求方法
                method: 'POST',
                //url
                url: '/axios-server',
                //其它参数
                params: {
                    a: 100,
                    b: 300
                },
                headers: {
                    uname: 'hi'
                },
                data: {
                    username: 'admin',
                    age: 30
                }
            }).then(response => {
                console.log(response)
                console.log(response.status)
            })
        })
    </script>

fetch函数发送请求

	<button>发送请求</button>
    <script>
        const btn = document.querySelector('button')
        btn.addEventListener('click', () => {
            fetch('http://127.00.1:8000/fetch-server', {
                method: 'POST',
                params: {
                    a: 100,
                    b: 300
                },
                headers: {
                    uname: 'hi'
                },
                body: 'username=admin&password=123'
            }).then(response => {
                // return response.text()//{"name":"三三"}
                return response.json()//{name: '三三'}
            }).then(response => {
                console.log(response)
            })
        })
	</script>

跨域

同源策略

客户端的url和请求服务端的url协议、域名、端口号必须完全相同

违背同源协议就是跨域

解决跨域问题
  • JSONP

    JSONP是非官方的跨域解决方案,只支持get请求

    它通过动态创建<script>标签来实现跨域请求和相应数据的获取。(它利用了浏览器允许加载不同域名下的JS文件的特性,将需要获取的数据以JS函数参数的形式返回给客户端,从而达到跨域目的

    function jsonp(url, callback) {
    var script = document.createElement('script');
    script.src = url + '\&callback=' + callback;
    document.body.appendChild(script);
    }

    jsonp('<http://example.com/api/getData?name=Tom&age=20>', 'handleResponse');

    function handleResponse(data) {
    console.log(data);
    }
  • CORS

    官方的解决跨域的方案,跨域资源共享

    服务器通过设置响应头信息中的 Access-Control-Allow-Origin 属性,允许客户端跨域访问自己的资源