AJAX的学习笔记(2)

148 阅读4分钟

fetch的使用

fetch接收一个URL字符串作为参数,默认向该url地址发出GET请求,返回一个Promise对象。

fetch('http://localhost:9527/upload/single').then().catch()

简单的实际例子

promise风格写法

fetch('https://api.github.com/users/ccf-666').then(res=>res.json()).then(body=>{
    console.log(body);
}).catch(err=>console.log(err));

上面示例中,fetch接收到的res是一个Stream对象,这意味着前端不用等到收到所有数据后才开始处理数据,而是可以收到一点处理一点(后面有例子说明)

async/await的写法

    async function readData(){
    try{
        const res=await fetch('https://api.github.com/users/ccf-666');
        cosnt resData=await res.json();
        console.log(resData);
    }catch(err){
        console.log(err)
    }
}

Response对象

从上的例子可以看到,fetch要经过两次then/await才能拿到数据。第一次then/await,fetch接收到响应头,此时可以直接通过返回的Respone对象获取相应的响应头信息。

cosnt res=await fetch('https://api.github.com/users/ccf-666');
//第一个属性   返回一个布尔值,表示请求是否成功
res.ok
//第二个属性  返回一个数字,表示HTTP响应的状态码(200)
res.status  
//第三个属性  返回一个字符串,表示HTTP响应的状态信息('OK')
res.statusText
//第四个属性  返回一个请求的url
res.url 
//第五个属性  返回一个字符串,代表请求的类型
// basic 代表同源请求   cors 代表跨域请求
//error 代表网络错误   还有其他类型

//第六个属性  返回一个布尔值,代表请求是否发生跳转
res.redirected

判断请求是否成功

fetch发出请求后,只有网络错误或者无法连接时,才会发生报错,其他情况不会发生报错,而是认定为成功。即使返回的状态码为4xx或5xx,fetch返回的Promise的状态也会变为Fulfilled

所以,需要通过Response.status/ok来判定请求是否成功。

//第一种
fetch('https://api.github.com/users/ccf-666').then(res=>{
    if(res.status>=200&&res.status<300)
    {
        return res.json();
    }else{
        throw new Error(res.statusText);
    }
}).then(body=>{
    console.log(body)
}).catch(err=>{
    console.log(err)
})
//第二种
    if(res.ok)
    {
        return res.json();
    }else{
        throw new Error(res.statusText);
    }

headers属性

Response对象还有一个headers属性,是一个Headers对象,代表着所有响应头信息。

image.png

Response读取数据的方法

res.json()  得到响应数据的json格式
res.text()  得到响应数据的文本字符串
res.blob()  得到响应数据的二进制 Blod对象
res.formData()  得到响应数据的FormData表单格式

clone方法

前面说到,fetch返回的res 是一个Stream对象,所以它只能读取一次,读完就不能再次读取。

let data1=await res.json();
let data2=await res.text();//发生报错

因此,有了clone这个方法,来创建res的副本。

const res=await fetch('https://api.github.com/users/ccf-666');
cosnt res2= res.clone();
let data1=await res.json();
let data2=await res2.text();//不发生报错

body属性

既然fetch返回的res是一个Stream对象,那么res可以一点一点获取,不用等到接收到所有数据才完成响应。Response.body属性就是用来实现这一点的,它是一个ReadableStream (可读流对象)。

const res=await fetch('xxx');
//获取流读取器
const reader =res.body.getReader();
while(true){
    cosnt {done,value}=await reader.read();
    if(done){
        break;
    }
    console.log(`每次接收到的数据:${value}`);
}

image.png getReader()返回的是ReadableStreamDefaultReader 可读流对象读取器 解析流的对象。reader.read()就是接收/读取流数据,所以是一个异步操作,每次读取器接收数据返回的有done和value,done表示是否所有数据是否读完了(fasle/true) value就是接收到的数据,它是一个Uint8Array。这个需要使用TextDecoder()进行解码才能获取到文本。

const decoder=new TextDecoder();
while(true){
        const {done,value}=await reader.read();
        // console.log(done);
        // console.log(value);
        if(done){
            break;

        }
        const txt=decoder.decode(value);
        console.log(txt);
    }

image.png

定制HTTP请求

配置对象

fetch()的第一个参数是URL,第二个参数是配置对象,可以设置请求方法,请求头,请求体

const res=await fetch(url,{
        method:'POST',
        headers:{
            'Content-type':'application/json'
        },
        body:JSON.stringify({
            "loginId":"admin1",
            "loginPwd":"123123"
        })

    })
    // console.log(res);
    const body=await res.json();
    console.log(body);

(先了解一下)配置对象有很多,下面是完整的:

image.png

取消请求

fetch请求发送后,如果想要取消,可以使用AbortController对象

const controller=new AbortController();
//1s后调用abort方法 取消请求
setTimeout(()=>controller.abort(),1000);
try{
    const res=await fetch(url,{
        signal:controller.signal
    })
}catch(err){
    console.log(err);
}

想要中途取消请求,需要给signal属性配置一个 controller.signal。 想要取消时,就要调用controller.abort()