我想知道是否有任何方法可以打破 UseEffect 的當前行程并讓它在下一次渲染時開始,就像這樣
...
useEffect(() => {
SlowFunction(update);
}, [update]);
setUpdate(1)
// a bit of time passes but not long enough for the SlowFunction(1) to be done
setUpdate(2)
//when this is called and the useEffect runs, stop the SlowFunction(1) and run SlowFunction(2)
像這樣在使用效果中呼叫我更新的個人功能,
const [update, setUpdate] = useState(0);
const [thisConst, setThisConst] = useState(0);
async function SlowFunction(firstParam, paramEtc, { signal } = {}) {
while (true) {
//wait two seconds between each
await new Promise((r) => setTimeout(r, 2000));
// Before starting every individual "task" in the function,
// first throw if the signal has been aborted. This will stop the function
// if cancellation occurs:
signal?.throwIfAborted();
// else continue working...
console.log('working on another iteration');
}
console.log('Completed!');
return 'some value';
}
useEffect(() => {
const controller = new AbortController();
const { signal } = controller;
(async () => {
try {
const result = await SlowFunction(update, 'some other value', {
signal,
});
setConst(result);
} catch (ex) {
console.log('EXCEPTION THROWN: ', ex);
}
})();
return () => controller.abort(new Error('Starting next render'));
}, [update]);
uj5u.com熱心網友回復:
AbortSignalAPI是處理取消的標準方法。
我將提供一個示例,說明如何將它與您的SlowFunction. 您需要接受一個中止信號作為可選引數,以便在下一次渲染發生時,可以取消該函式。
這是一個示例可取消函式:
async function SlowFunction (firstParam, paramEtc, {signal} = {}) {
for (let i = 0; i < 1_000_000; i = 1) {
// Before starting every individual "task" in the function,
// first throw if the signal has been aborted. This will stop the function
// if cancellation occurs:
signal?.throwIfAborted();
// else continue working...
console.log('working on another iteration');
}
return 'some value';
}
您可以像這樣在效果掛鉤中使用它:回傳一個呼叫abort控制器上的方法的清理函式:
useEffect(() => {
const controller = new AbortController();
const {signal} = controller;
(async () => {
try {
const result = await SlowFunction(update, 'some other value', {signal});
setConst(result);
}
catch (ex) {
// Catch the exception thrown when the next render starts
// and the function hasn't completed yet.
// Handle the exception if you need to,
// or do nothing in this block if you don't.
}
})();
return () => controller.abort(new Error('Starting next render'));
}, [update]);
如果該函式在下一次渲染發生之前完成,則該abort操作將沒有效果,但如果尚未完成,則在下一次到達該陳述句signal?.throwIfAborted();時,該函式將拋出例外并終止。
更新以回應您的評論:
如果您的 JavaScript 運行時太舊而無法支持該AbortSignal.throwIfAborted()方法,您可以通過替換該行來解決這個問題:
signal?.throwIfAborted();
和:
if (signal?.aborted) {
throw signal?.reason ?? new Error('Operation was aborted');
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/537116.html
上一篇:使用PHPickerViewController和UIImagePickerController是否需要請求權限?
