2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
🧑💻 写在开头
点赞 + 收藏 === 学会🤣🤣🤣
There is also an abort method on the instantiated XMLHttpRequest object
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', function(e) {
console.log(this.responseText);
});
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
xhr.send();
// 返回
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
If you cancel directly after sending
// xhr的取消操作:执行过程比较模糊,不知道abort什么时机进行处理
xhr.abort()
If you cancel the request during the timer (when the timer duration is about the same as the interface request duration), you will find that the resource has been obtained, but the console does not print
const ac = new AbortController();
const { signal } = ac;
const url = "https://jsonplaceholder.typicode.com/todos/1";
fetch(url, { signal })
.then((res) => res.json())
.then((json) => console.log(json));
Use abort to cancel the request directly
ac.abort()
The reason for the error here is that the error is not captured
// 修改后的代码
fetch(url, { signal: ac.signal })
.then((res) => res.json())
.then((json) => console.log(json))
.catch(e => console.log(e)) // DOMException: signal is aborted without reason
ac.abort() // abort接受一个入参,会被传递到signal的reason属性中
Why can it be cancelled like this?
fetch monitors the status of the signal object and terminates the request
const ac = new AbortController();
const { signal } = ac;
const url = "https://jsonplaceholder.typicode.com/todos";
const todoRequest = (id, { signal }) => {
fetch(`${url}/${id}`, { signal })
.then((res) => res.json())
.then((json) => console.log(json))
.catch((e) => console.log(e)); // DOMException: signal is aborted without reason
};
todoRequest(1, { signal });
todoRequest(2, { signal });
todoRequest(3, { signal });
ac.abort("cancled");
Is an interface that represents a signal object that allows you to communicate with an executing asynchronous operation so that it can be aborted before completion.
Static method used to create an aborted AbortSignal object. When you call this method, it returns an AbortSignal instance with the aborted status set to true.
const signalAbout = AbortSignal.abort(); // AbortSignal {aborted: true, reason: DOMException: signal is aborted without reason...}
Used to check if the AbortSignal has been aborted before executing the code. If the AbortSignal has been aborted, it will throw an AbortError. This method can help developers ensure that it has not been aborted before performing specific operations to avoid unnecessary processing.
const signalAbout = AbortSignal.abort('abortedReason');
try {
signalAbout.throwIfAborted(); // 抛出error: abortedReason
} catch (error) {
console.log(error);
}
Used to create an AbortSignal object that automatically aborts after a specified time. This is useful when you need to set a request timeout.
// 使用 AbortSignal.timeout 设置 10ms超时
const signalAbout = AbortSignal.timeout(10);
const todoRequest = (id, { signal }) => {
fetch(`${url}/${id}`, { signal })
.then((res) => res.json())
.then((json) => console.log("json: ", json))
.catch((e) => console.log("err: ", e)); //DOMException: signal timed out
};
todoRequest(1, { signal: signalAbout });
AbortSignal inherits from EventTarget because AbortSignal is used to listen to abort events, and EventTarget provides a mechanism for adding, removing, and triggering event listeners.
const signalAbout = AbortSignal.timeout(10);
signalAbout.addEventListener("abort", (e) => {
console.log("aborted: ", e);
})
The printout of e is as follows:
const ac = new AbortController();
const { signal } = ac;
const cancelablePromise = ({signal}) =>
new Promise((resolve, reject) => {
// 情况1:直接主动取消
signal?.throwIfAborted(); // 也可以用reject
// 情况2:正常处理业务逻辑
setTimeout(() => {
Math.random() > 0.5 ? resolve('data') : reject('fetch error');
}, 1000);
// 情况3:超时 todo?
// 监听取消
signal.addEventListener("abort", () => {
reject(signal?.reason);
});
})
// 发起网络请求
cancelablePromise({signal})
.then(res => console.log('res: ', res))
.catch(err => console.log('err: ', err))
// 情况1
// ac.abort('用户离开页面了') // err: 用户离开页面了
// 情况2 正常请求 err: fetch error || res: data
When multiple event listeners are added to an element, you do not need to cancel each event once like removeEventListener, and you need to specify the event handler of the corresponding event each time.
When using signal, you only need to cancel the signal once, and all event listeners will be canceled.
const ac = new AbortController();
const { signal } = ac;
const eleA = document.querySelector('#a');
const eleB = document.querySelector('#b');
function aEleHandler () {}; // 事件
eleA.addEventListener('click', aEleHandler, {signal}); // 无论绑定多少个事件,都只需要一个signal
eleB.addEventListener('click', () => {
ac.abort(); // 只需要取消一次
})
When the network speed is not good, how to cancel this continuous network request?
const ac = new AbortController();
const { signal } = ac;
const fetchAndRenderAction = (signal) => {
requestData(signal); // 多个串行或者并行的接口
drawAndRender(signal); // 异步渲染
}
try{
fetchAndRenderAction({signal})
}catch{
// dosomething...
}
When the user leaves the page on his own initiative, or the user's network is very slow (the expected return order is: interface 1 => interface 2; but interface 1 returns too slowly, resulting in a disordered order), the request needs to be terminated manually. The instance semaphore signal (which can be stored as a ref) of the constructor AbortController is used as a parameter of fetch. At each request, the abort method can be manually called to cancel the previous request.
If it is helpful to you, you are welcome to follow me. I will update the technical documentation regularly so that we can discuss and learn together and make progress together.