Как создать сигнал, который задерживает базовый сигнал и немедленно очищается

Я хочу сделать сигнал, который настраивается на базовый сигнал или заметку после определенной задержки и немедленно очищается, если базовый сигнал очищается. Следующий код демонстрирует то, что я хочу.

      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 ответ

Ваша попытка была полностью оправдана.

В, хотя похоже, что у него похожий вариант использования, здесь он не будет работать, как задумано, потому что:

  1. Тайм-аут прошел до createDeferredэто не точное количество времени, которое он будет ждать, прежде чем вызывать обновления — это максимальное время ожидания, прежде чем браузер станет бездействующим.
  2. Тайм-аут произойдет до обновления сигнала до и других значений.
      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));
Другие вопросы по тегам