下面的代码,如果 count 连续发生两次变化,那么 loading 的状态就会被错误的提前设置为 false,怎么解决这个问题?
useEffect(() => {
console.log("set loading: true");
setLoading(true);
const ac = new AbortController();
new Promise<void>((resolve, reject) => {
const timer = setTimeout(() => {
console.log("resolve");
resolve();
}, 3000);
ac.signal.addEventListener("abort", () => {
clearTimeout(timer);
reject("abrted");
});
})
.then(() => {
setLazyCount(count);
})
.catch((err) => {
console.log("error:", err);
})
.finally(() => {
console.log("finally set loading: false");
setLoading(false);
});
return () => {
ac.abort();
console.log("abort");
};
}, [count]);
我尝试过把设置 loading 为true 的代码用 setTimeout 包裹起来,这样可以正确设置 loading,但是,当 Promise 立即完成的时候,顺序就又错误了。
useEffect(() => {
setTimeout(() => {
console.log("set loading: true");
setLoading(true);
});
const ac = new AbortController();
new Promise<void>((resolve, reject) => {
const timer = setTimeout(() => {
console.log("resolve");
resolve();
// ...
然后把这个部分全部放在 settimeout 中才可以,但是这样写也太别扭了
useEffect(() => {
const ac = new AbortController();
setTimeout(() => {
console.log("set loading: true");
setLoading(true);
new Promise<void>((resolve, reject) => {
const timer = setTimeout(() => {
console.log("resolve");
resolve();
}, 3000);
ac.signal.addEventListener("abort", () => {
clearTimeout(timer);
reject("abrted");
});
})
.then(() => {
setLazyCount(count);
})
.catch((err) => {
console.log("error:", err);
})
.finally(() => {
console.log("finally set loading: false");
setLoading(false);
});
});
return () => {
ac.abort();
console.log("abort");
};
}, [count]);
在线测试 https://codesandbox.io/p/sandbox/use-effect-loading-fshhvm?fi...
在你的代码逻辑里看起来不应该直接用true或者false来判断。
这边提供一个思路:
应该设置一个全局变量 LoadingNum初始化为0,大于0的时候加载loading
你的代码里设置为true的时候执行LoadingNum++
你的代码里设置为false的时候执行LoadingNum--
这样可以避免应前一次结束影响下一次loading加载