什么是异步
在单线处理的命令逻辑中,将耗时较长的程序从queue里拎出来,延迟?时间后,再callback回执行队列里,让该程序的执行不影响其他线性运行的程序
异步流程
1. 拎出需要异步的命令,延长xx时间setTimeOut…
setTimeOut(具体执行语句,延长时间)
2.1 执行异步请求->单个请求
如使用XMLHttp, Promise, fetch API。此处以fetch API为例。
1. 向目标server发出HTTP request,要求返回一个promise
fetch方法有两个参数,第一个是target url,第二个是针对HTTP request配置对象的不同属性可以调用的不同方法
method: 表示 HTTP 请求的方法,可以是 ‘GET’、‘POST’、‘PUT’ 等。默认值是 ‘GET’。
headers: 包含请求头的对象,可以设置各种请求头,如 ‘Content-Type’、‘Authorization’ 等。
body: 包含请求主体的内容,通常用于 POST 请求。可以是一个字符串、一个 FormData 对象,或者一个 URLSearchParams 对象等。
mode: 表示请求的模式,例如 ‘cors’、‘no-cors’、‘same-origin’ 等。
cache: 表示请求的缓存模式,如 ‘default’、‘no-store’、‘reload’ 等。
credentials: 表示是否发送凭据,如 cookies。可以是 ‘same-origin’、‘include’、‘omit’。
redirect: 表示遇到重定向时要采取的操作,如 ‘follow’、‘error’、‘manual’。
referrer: 表示请求的 referrer,可以是 ‘no-referrer’、‘client’、URL 等。
integrity: 包含请求的子资源完整性的字符串,用于校验文件完整性。
fetch('url',{
method:'GET'
})
2. 获得HTTP response,从中提取想要的属性
此时获得的(response)是整个HTTP响应,包括.status, .statusText, .json, .headers, .url等
- .status: 状态码,如200表示正常
- .json: json data,通过.json()来获取
此处以获取json data为例,此时server返回两种情况:1.有error 2.正常
fetch('url').then(response =>{
if(!response.ok){ //1.有error,throw之
throw Error('could not fetch the data for that resource');
}return response.json(); //2.正常return json data
})
3. 对获取的data分为两种情况:reject/resolve
- resolve: 处理data
- reject: catch error
fetch('url')
.then(response =>{
return response.json();
})
.then(data =>{
//execute data...
})
.catch(error(err=>{
//catch error...
err.message...
})
2.2 执行异步请求->单个请求->需要取消异步请求
1. 设置需要取消异步请求的条件
使用 useEffect(func, conditions) ,令监测到conditions情况变化,或组件被激活卸载时,就执行函数func
示例:url变化或组件被卸载时激活 useEffect(func …,[url])
2. 创建一个AbortController控制器
const abortCont = new AbortController();
3. 让AbortController和下文的fetch异步操作相关联
AbortSignal 传给 fetch:fetch(url, { signal: abortCont.signal })
4. 在fun中返回一个清理函数
return () => abortCont.abort()
- 该函数执行场景:当组件要被卸载时 or 下一次url变化时
- 该函数执行用途:中止用AbortController关联的对应fetch异步操作,避免出现上述情况后仍然在进行异步
useEffect(() => {
//2.创建一个AbortController控制器
const abortCont = new AbortController();
setTimeout(() => {
//3.AbortSignal 传给 fetch,让AbortController和fetch异步操作相关联
fetch(url, { signal: abortCont.signal })
.then// ... (省略了一些代码)
},1000);
//3.返回一个清理函数
return () => abortCont.abort();
}, [url]); //1.设置需要取消异步请求的条件
3. 执行异步请求->多个请求
关于async和await:
- async:声明此函数为异步函数,并回返回一个promise对象(两种情况:resolve/reject)
- await:暂停函数执行,等待promise解决
- 设定发起单个异步请求的方法 const fetchData
- 批量处理所有的异步请求const func。用promise.all等待所有请求处理好后返回再return result
- 执行所有请求的数据处理。func().then.catch
//设定单个异步请求的发起
const fetchData = async (url) => {
const response = await fetch(url);
const data = await response.json();
return data;
};
const func = async () => {
const urls = ['url1', 'url2', 'url3']; // 替换为实际的URL数组
const promises = urls.map(url => fetchData(url));
try {
const results = await Promise.all(promises);
return results;
} catch (error) {
console.error('An error occurred:', error);
throw error;
}
};
func().then(data => {
//execute data
}).catch(error => {
//catch error
});
具体示例
import { useState, useEffect } from "react";
const useFetch = (url) => {
// 设定data,pending和error三种状态
const [data, setData] = useState(null);
const [isPending, setIsPending] = useState(true);
const [error, setError] = useState(null);
//异步的两种情况:正常异步,需要中止异步
useEffect(() => {
const abortCont = new AbortController();
setTimeout(() => {
//中止异步:把AbortController连接到这个fetch上,好监测useEffect的url发生变动的情况从而执行abortCont.abort()中止异步
fetch(url, { signal: abortCont.signal })
// 正常异步:这一步return json格式的数据
.then((res) => {
//对返回的HTTP对象分两种情况:reject和resolve,如果reject,则throw error,反之return json data
if (!res.ok) {
throw Error("could not fetch the data for that resource");
} else {
return res.json();
}
})
//这一步接收res.json,并对data执行操作:改变三个状态值
.then((data) => {
setIsPending(false);
setData(data);
setError(null);
})
//这一步对throw出来的error进行处理
.catch((err) => {
if (err.name === "AbortError") {
console.log("fetch aborted");
} else {
setIsPending(false);
setError(err.message);
}
});
}, 1000);
//若触发[url],则执行func->return abortCont.abort()
return () => abortCont.abort();
}, [url]);
//最后对之前设置的三个状态数据都return
return { data, isPending, error };
};
export default useFetch;