CodeSampleX

Пример

nanostores 1.4.2: Work out what nanostores' lazy mounting actually does: which argument of a listener is the changed key, why .get() fires onMount and re-runs it every second, why a computed store accepts .set(), and why .value and .get() disagree

Проверенный пример — npm nanostores 1.4.2: Work out what nanostores' lazy mounting actually does: which argument of a listener is the changed key, why .get()…

sha256:2bad4d8c3646df6d3f3c67f5c83c45192b4aa22c2f9b886001b21a310347289f

Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла. Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди. MIT-0

Свидетельства выполнения

Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.

Основа свидетельства
Подписанный контракт пройден
Квитанции проверки
1
Ключи подписи, собравшие его
1
Заявленная среда node 22 linux x64 node 22 javascript npm

Среды запусков проверки

Окружение Контракт Этапы Запуск
node 22 · linux alpine/x64 · docker ed25519:a2ec939a4c60e243 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-14

Кейс

HOW
Цель
Work out what nanostores' lazy mounting actually does: which argument of a listener is the changed key, why .get() fires onMount and re-runs it every second, why a computed store accepts .set(), and why .value and .get() disagree
Пакеты
Символы
  • nanostores.atom
  • nanostores.map
  • nanostores.computed
  • nanostores.batch
  • nanostores.onMount
  • nanostores.keepMount
  • nanostores.cleanStores
  • nanostores.listenKeys
  • nanostores.deepMap
  • nanostores.readonlyType
  • nanostores.task
  • nanostores.allTasks
  • nanostores.STORE_UNMOUNT_DELAY
  • Store.listen
  • Store.subscribe
  • Store.setKey
  • Store.get
  • Store.value
  • Store.lc
  • globalThis.nanostoresGlobal
Окружение
node 22
Создан
2026-08-14T20:16:45Z

Контракт

  1. assert every store, atom and map alike, calls its listeners as (value, oldValue, changedKey), so a map listener's second argument is the previous whole object and the changed key arrives third
  2. assert an atom fills all three slots and leaves the third undefined, which is why the changed key cannot be the second argument
  3. assert subscribe's priming call passes exactly one argument, so arguments.length is the only thing separating it from a real change whose previous value was undefined
  4. assert setKey(key, undefined) deletes the key rather than storing undefined, so `key in value`, Object.keys and JSON.stringify all lose the field
  5. assert deleting an already absent key is not a change and notifies nobody
  6. assert set() compares with === and nothing deeper, so an equal-looking new object is a change while the store's own current object is not
  7. assert readonlyType is an identity function returning the very same store object, so nothing about read-only-ness reaches runtime
  8. assert .set() on a computed store neither throws nor is ignored, and that the written value sticks across re-reads until one of its own dependencies really moves
  9. assert a fresh computed's .value property reads undefined while .get() returns the computed number, so the two disagree until the first mount
  10. assert .get() on an unmounted store runs the onMount initializer and returns with the listener count back at zero, so reading is not passive
  11. assert repeat reads inside the delay window do not re-mount, because the store is still flagged active
  12. assert STORE_UNMOUNT_DELAY is 1000 and the onMount cleanup runs on that timeout rather than when the last listener leaves
  13. assert that same delay makes a store which is only ever read with .get() re-run its mount side effect once the window expires
  14. assert batch() collapses many writes into a single listener call carrying the final value, the value from before the first write, and an undefined changed key
  15. assert the same two writes unbatched deliver two calls, each naming its own key
  16. assert listenKeys stays quiet for an unwatched key and fires for a watched one in both modes: batched, where it must diff old against new because the key argument is missing, and unbatched, where the key is present and Set membership decides
  17. assert the computed callback does not run at construction and does not re-run on repeat reads
  18. assert an unrelated store's change bumps the single epoch counter that nanostores parks on globalThis so separately bundled copies share it, leaving the recompute guard stale, and that the callback still does not re-run because the per-store argument comparison is unchanged
  19. assert the callback re-runs only when this store's own dependency actually moves
  20. assert a plain async arrow in computed() stores the Promise object itself as the store value, with no warning and no throw, because the async path is gated on a .t marker rather than on being a thenable
  21. assert the identical shape wrapped in task() does take that path, warning that Promise support in computed() is going away and leaving the store undefined at the moment get() returns
  22. assert awaiting allTasks() is still too early to read that value, because it resolves before the .then() computed chained onto the same promise, and the value only appears a turn later
  23. assert keepMount returns undefined because it discards the unsubscribe function, and that no dropMount export exists to undo it
  24. assert cleanStores throws "cleanStores() can be used only during development or tests" when NODE_ENV is production, rather than degrading to a no-op
  25. assert cleanStores outside production unmounts a pinned store synchronously, skipping the 1000 ms delay
  26. assert deepMap still exports from the core package but announces on construction that it moved to @nanostores/deepmap and will be removed in 2.0, and that its setKey takes a dotted path that descends rather than creating a literal dotted key
  27. assert that notice is deduped by exact message text, so a second deepMap is silent and the deprecation can be missed entirely
  28. assert the core package has no create, createStore or useStore, the names carried over from the better known zustand/jotai/redux family

Файлы

  • csx.json
  • package-lock.json
  • package.json
  • src/stores.mjs
  • test/contract.mjs

Скачать артефакт с исходным кодом (tar.gz)

Исходный сидер

anonymous