ajax技术

2021/12/19

# 服务器代码

  • 为了测试方便,自己开一个服务器,请求和响应分别放在不同的位置














 
 
 
 
 
 
 





 
 
 


const express = require('express');
const app = new express();
app.listen(8888,() => {
    console.log('listen 8888');
});

app.get('/', (req, res) => res.send(`
<body>
    <div>这是</div>
    <div>首页</div>
    <div>内容</div>

    <script>
        setTimeout(() => {
            const xhr = new XMLHttpRequest();
            xhr.addEventListener('load', function() {
                const obj = JSON.parse(this.responseText);
                console.log(obj.data);
            });
            xhr.open('get', 'http://localhost:8888/data');
            xhr.send();
        }, 2000);
    </script>
</body>
`));

app.get('/data', (req, res) => res.send({
    data: '异步请求'
}));

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

# 方法

# open

  • 作用:初始化一个请求
  • 调用:xhr.open(method, url[, async, user, password])
  • 入参:String, String, Boolean, String, String
  • tip:参数3决定是否异步,默认true。一般不设置false,性能不好

# send

  • 作用:将请求发送出去
  • 调用:xhr.send(body)
  • 入参:document | FormData | Blob | URLSearchParams
  • node解析body需要安装body-parser


 
 
 



















 
 






 


 


const express = require('express');
const app = new express();
const bdParser = require('body-parser');
app.use(bdParser.urlencoded({extended:false}));
app.use(bdParser.json());
app.listen(8888, () => {
    console.log('listen 8888');
});

app.get('/', (req, res) => {
    res.send(`
<body>
    <div>首页</div>
    <script>
        setTimeout(() => {
            const xhr = new XMLHttpRequest();
            
            xhr.addEventListener('load', () => console.log(xhr.response));
            xhr.open('POST', 'http://localhost:8888/data');

            const params = {
                name: 'hdy',
                age: 18
            }
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.send(JSON.stringify(params));
        }, 2000);
    </script>
</body>
`)});

app.post('/data', (req, res) => {
    console.log(req.body);

    // express处理post请求返回必须是对象或序列化对象【JSON.stringify()】
    res.send(req.body);
})
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

# setRequestHeader

  • 作用:设置请求头
  • 调用:xhr.setRequestHeader(key, value)
  • 入参:String, String





 


const xhr = new XMLHttpRequest();

xhr.addEventListener('load', () => console.log(xhr.response));
xhr.open('GET', 'http://localhost:8888/data');

xhr.setRequestHeader('Cache-Control', 'catch');
xhr.send();
1
2
3
4
5
6
7

# abort

  • 作用:终止请求
  • 调用:xhr.abort()
  • 服务器要执行两秒,一秒钟后会取消,所以拿不到返回值





 
 

const xhr = new XMLHttpRequest();
xhr.addEventListener('load', () => console.log(xhr.response))
xhr.open('GET', 'http://localhost:8888/data');
xhr.send();

// 一秒钟后取消
setTimeout(() => xhr.abort(), 1000);
1
2
3
4
5
6
7
app.get('/data', (req, res) => {
    const end = Date.now() + 2000;
    while (Date.now() < end) {}
    res.send();
})
1
2
3
4
5

# getResponseHeader

  • 作用:获取某一个响应头的值
  • 调用:xhr.getResponseHeader(key)
  • 入参:String
  • 返回:String
const xhr = new XMLHttpRequest();


xhr.addEventListener('load', () => 
    console.log(xhr.getResponseHeader('X-Powered-By'))
); // Express

xhr.open('GET', 'http://localhost:8888/data');
xhr.send();
1
2
3
4
5
6
7
8
9

# getAllResponseHeaders

  • 作用:拿到所有响应头
  • 调用:xhr.getAllResponseHeaders()
  • 返回:string
const xhr = new XMLHttpRequest();

// 返回带换行符的String,展现出所有的Headers
xhr.addEventListener('load', () => console.log(xhr.getAllResponseHeaders()))
xhr.open('GET', 'http://localhost:8888/data');
xhr.send();
1
2
3
4
5
6

# overrideMimeType

  • 作用:强制指定返回的MIME类型
  • 调用:xhr.overrideMimeType(type)
  • tip:必须在send前指定

# 属性

# responseType

  • 作用:用于判断响应的类型,response接受到值后做出对应的改变
  • 必须要在send前修改,否则无效
responseType的值 response的值
"" DOMString对象中的文本【默认】
text DOMString对象中的文本
document HTTP document或XML document对象
json json解析后的对象
ArrayBuffer 包含二进制数据的ArrayBuffer
blob 包含二进制对象的Blob对象

# response

  • 作用:响应结果
  • 值:根据responseType的值决定
  • 需要在【下载响应数据中】readyState >= 3 以后才有值

# responseText

  • 作用:后端返回的文本
  • 值:String
  • 注:DOMString也是以String的形式返回的

# onreadystatechange

  • 注:此属性没有驼峰写法
  • 作用:当xhr对象readyState状态发生变化时内部调用钩子
  • 调用:xhr.onreadystatechange = function () {}
const xhr = new XMLHttpRequest();
console.log(xhr.readyState); // 0
xhr.onreadystatechange = () => console.log(xhr.readyState);

setTimeout(() => xhr.open('get', 'http://localhost:8888/data'), 1000); // 1
setTimeout(() => xhr.send(), 2000); // 2 3 4
1
2
3
4
5
6

# readyState

阶段 对应XMLHttpRequest的静态属性
0 创建未调用 open() 方法 UNSENT
1 已调用open方法 OPENED
2 已调用send方法 HEADERS_RECEIVED
3 下载数据中 LOADING
4 数据下载完成 DONE
<body>
    <script>
        const xhr = new XMLHttpRequest();

        console.log(xhr.readyState); // 0
        console.log(XMLHttpRequest.UNSENT); // 0
        console.log(XMLHttpRequest.OPENED); // 1
        console.log(XMLHttpRequest.HEADERS_RECEIVED); // 2
        console.log(XMLHttpRequest.LOADING); // 3
        console.log(XMLHttpRequest.DONE); // 4
    </script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12

# responseXML

  • 作用:存储返回值的HTML或XML对象

 


 




const xhr = new XMLHttpRequest();
xhr.responseType = 'document';
xhr.addEventListener('load', () => {
    console.log(xhr.response); // #document
    console.log(xhr.responseXML === xhr.response); // true
});
xhr.open('GET', 'http://localhost:8888/data');
xhr.send();
1
2
3
4
5
6
7
8
// 返回
app.get('/data', (req, res) => {
    res.send('<div>返回盒子</div>');
})
1
2
3
4

# timeout

  • 设置超时时间,如果响应超时,就会触发ontimeout事件
  • 应该在【open之后】【send之前】设置




 

 
 


const xhr = new XMLHttpRequest();
const start = Date.now();
xhr.addEventListener('load', () => console.log(xhr.response+ (Date.now() - start)));
xhr.open('GET', 'http://localhost:8888/data');
xhr.timeout = 2000;

// 输出: 2002
xhr.ontimeout = () => console.log('timeout:' + (Date.now() - start));
xhr.send();
1
2
3
4
5
6
7
8
9
app.get('/data', (req, res) => {
    const end = Date.now + 3000;
    while (Date.now < end) {}
    res.send('处理了三秒');
})
1
2
3
4
5

# upload

  • 值:一个XmlHttpRequestUpload对象,给它绑定事件监听器来查看上传的进度
addEventListener 触发
onloadstart 开始获取
onprogress 正在传输
onabort 操作终止
onerror 失败
onload 成功
ontimeout 上传超时
onload 获取完成(不论成功与否)

# withCredentials

  • 作用:跨域访问时是否可以携带cookies
  • 值:Boolean

# status

含义
200 成功
301 永久重定向
302 临时重定向成功
304 协商缓存命中【Not Modified】
401 请求需身份验证
403 服务器拒绝执行
404 页面未找到
500 服务器错误
501 此请求方法不被服务器支持【get/post/...】


 
 




const xhr = new XMLHttpRequest();
xhr.addEventListener('load', () => {
    console.log(xhr.status); // error... 500
    console.log(xhr.response); // 错误信息
});
xhr.open('GET', 'http://localhost:8888/data');
xhr.send();
1
2
3
4
5
6
7


 


// 返回
app.get('/data', (req, res) => {
    res.status('500').send('错误信息');
})
1
2
3
4

# responseURL

  • 作用:拿到最终返回的后端URL
  • tip:无论中间经历过多少重定向,都会返回最后的一个URL,且去掉锚点【#】


 





const xhr = new XMLHttpRequest();
xhr.addEventListener('load', () => {
    console.log(xhr.responseURL); // http://localhost:8888/error
    console.log(xhr.response); // 错误
});
xhr.open('GET', 'http://localhost:8888/data');
xhr.send();
1
2
3
4
5
6
7


 






// 返回重定向
app.get('/data', (req, res) => {
    res.redirect('http://localhost:8888/error');
})

app.get('/error', (req, res) => {
    res.send('错误');
})
1
2
3
4
5
6
7
8

# statusText

  • 作用:当前相应的状态值,只有readyState > 3 才有值
  • 成功响应且服务器没有给具体的状态文本信息时,值为【OK】


 
 



const xhr = new XMLHttpRequest();

// 0:'' 200:OK
xhr.onreadystatechange = () => console.log(xhr.status + ":" + xhr.statusText);
xhr.open('GET', 'http://localhost:8888/data');
xhr.send();
1
2
3
4
5
6

# 事件

events

事件 触发
load 【请求完成】时触发
onreadystatechange readyState变化时触发
timeout 超时触发
abort 请求被终止时触发
error 请求过程遇到错误时触发
loadstart 下载开始触发
loadend 加载进度停止之后被触发【在error/abord/load等事件触发之后触发】
progress 在接受到数据时周期性触发【适合返回数据较大时查看进度使用】
上次更新: 11/1/2024