Как создать сигнал, который задерживает базовый сигнал и немедленно очищается
Я хочу сделать сигнал, который настраивается на базовый сигнал или заметку после определенной задержки и немедленно очищается, если базовый сигнал очищается. Следующий код демонстрирует то, что я хочу.
import { render } from "solid-js/web";
import { For, createSignal, createEffect } from "solid-js";
function Counter() {
const [s, setS] = createSignal(undefined)
const [delayedS, delayedSetS] = createSignal(undefined)
setTimeout(() => {
setS(10)
}, 1000)
setTimeout(() => {
setS(undefined)
}, 3000)
createEffect(() => {
let res = s()
if (res !== undefined) {
setTimeout(() => delayedSetS(res), 1000)
} else {
delayedSetS(undefined)
}
})
return (<>
<span> S {s()} </span>
<span> Delayed S {delayedS()}</span>
</>)
}
render(() => <Counter />, document.getElementById("app"));
Это работает, хотя это правильный подход. Я не уверен, предоставляет ли createDeferred эту функциональность, хотя я не хочу ее использовать, так как она использует планировщик, я не уверен, что он делает.
1 ответ
Ваша попытка была полностью оправдана.
В, хотя похоже, что у него похожий вариант использования, здесь он не будет работать, как задумано, потому что:
- Тайм-аут прошел до
createDeferred
это не точное количество времени, которое он будет ждать, прежде чем вызывать обновления — это максимальное время ожидания, прежде чем браузер станет бездействующим. - Тайм-аут произойдет до обновления сигнала до и других значений.
const delayedS = createDeferred(s)
Предпочтительным примитивом для установки сигналов являетсяcreateComputed
. Это чистое вычисление — аналогично
createMemo
– это означает, что он будет работать непосредственно перед эффектами. В простых примерах обычно нет разницы в использовании эффекта, но использование эффекта для установки сигналов потенциально может привести к большему количеству обновлений, чем необходимо.
createComputed(
on(s, (v) => {
if (v) setTimeout(() => setDelayedS(v), 1000);
else setDelayedS();
})
);
Кроме того, очистка тайм-аута на наборе для
undefined
это происходит без задержки, может устранить некоторые временные сбои.
let timeoutId = 0;
createComputed(
on(s, (v) => {
if (v) timeoutId = setTimeout(() => setDelayedS(v), 1000);
else {
setDelayedS();
clearTimeout(timeoutId);
}
})
);
onCleanup(() => clearTimeout(timeoutId));