
Product
Rust Support Now in Beta
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
@timberstack/echoes
Advanced tools
The echoes
package is a very simple and straight-forward implementation of the Observer Pattern. It also takes inspiration from several niceties found in RxJs and Signals, such as:
subscribe
and unsubscribe
-like methods (RxJs)until
method (RxJs)Besides:
This package is pretty new and we don't expect a crazy wild adoption. The API and the implementation are fairly simple, but please be aware that bugs might appear. If you find anything strange, please let us know by opening an issue.
Even though it's under active development, the API is stable and it's very unlikely to change. However, until we don't hit a v1, we cannot ensure that the API will remain intact. There are still a lot of work to do and we will try our best to not change the usage. But if a fix requires changing the API in order to keep the bundle size small, we should be open to minor adjustments.
pnpm add @timberstack/echoes
...
import { echo, computed } from "@timberstack/echoes"
<!-- ESM -->
<script type="module">
import { echo, computed } from "https://unpkg.com/@timberstack/echoes/dist/echoes.esm.js"
</script>
<!-- IIFE -->
<script src="https://unpkg.com/@timberstack/echoes/dist/echoes.iife.js"></script>
<script>
// Stored under the emitters global name so we don't pollute the global scope
const { echo, computed } = window.Echoes
</script>
[!CAUTION] These examples should be used for development only. If you plan to use the CDN for production, pin a specific version. For instance:
https://unpkg.com/@timberland/emitters@0.0.4/dist/emitters.esm.js
. Check the releases section for getting the latest version.
echo(optionalInitialValue)
The echo
function creates a new echo instance with an optional initial value:
const $count = echo(0)
const $map = echo(new Map())
const $statelessEvent = echo()
echo.value
This will return the current value of the echo (if any). Feel free to access it anywhere in your code, as it won't register or trigger any side effects:
$count.value // -> 0
$map.value // -> Map instance
$statelessEvent.value // -> null
echo#subscribe
It accepts a callback that will be triggered whenever the next
or trigger
methods are invoked. The callback will receive the current value of the Emitter or any message provided with the trigger
method.
$count.listen((count) => console.log(count))
$map.listen((map) => console.log(map.get('awesomeKey'))
$statelessEvent.listen((optionalMessage) => console.log(optionalMessage ?? 'No message provided'))
Subscriptions are not lazy by default. They will run as soon as declared. If you need to run it lazily, you can pass an object with the lazy
property set as true
as a second argument:
$count.listen(count) => doSomething(), { lazy: true })
In any case, it will return a Listener
object. More on it later.
echo#next
This method will be responsible for mutating the value and triggering all subscriptions. You can either provide a new value directly or through a callback (recommended for complex data types):
$count.next(2) // -> will set the value to 2 and trigger all subscriptions
$map.next((prev) => prev.set('hello', 'world')) // -> will mutate the value and then trigger the subscriptions
$statelessEvent.next('now we have value') // -> not recommended, but possible
computed(callback, [dependencies])
The computed
constructor returns an echo-like object with only a listen
method and a value property. Its value will be computed based on the callback's return value and the echoes contained within the dependencies array:
const $double = computed() => $count.value * 2, [ $count ])
Behind the scenes, it is creating an internal echo whose value is being updated every time the value of any of its dependencies change:
$double.listen(value) => console.log(value))
$count.next(2) // -> will log 4
Listener
Any listen
method will return a Listener
object that we can use to clear the listening itself.
Listener#mute
This will clear the listening on-demand:
const $count = echo(0)
const listener = $count.listen((value) => console.log(value))
$count.next( $count.value + 1 ) // -> will log 1
listener.mute()
$count.next( $count.value + 1 ) // -> won't log anything
Listener#until
Heavily inspired by the takeUntil
method from RxJs. Useful when we want the listening to take place only until a certain condition is met:
const $count = echo(0)
const listener = $count.listen(value) => console.log(value))
listener.until((value) => value > 2)
$count.next( $count.value + 1 ) // -> will log 1
$count.next( $count.value + 1 ) // -> will log 2
$count.next( $count.value + 1 ) // -> won't log anything
Listener#trigger(optionalMessage)
This will trigger the callback without mutating the value of the Emitter. Useful for when we have a stateless Emitter. Optionally, it takes a message that will be passed on to the callback:
const $onMessage = echo()
const messageEvent = $onMessage.listen(msg) => console.log(msg ?? 'no message provided'))
messageEvent.trigger('Hello world') // will log 'Hello world'
messageEvent.trigger() // will log 'no message provided'
MIT
FAQs
Lightweight reactivity library for vanilla JS
We found that @timberstack/echoes demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.