sig-js
v0.5.5
Published
high-level reactive-style programming in javascript
Downloads
60
Readme
sig
high-level reactive-style programming in javascript
var s = sig()
s.map(function (x) {
return x + 1
})
.filter(function (x) {
return !(x % 2)
})
.each(sig.log)
.done()
s.put(1) // 2
.put(2)
.put(3) // 4
docs
overview
sources and targets
Signals can have at most one source and multiple targets, where values and errors flow from the source to its targets.
value propagation
Values propagate from a source signal to its target signals using
.put()
. .put()
sends the given value to the value handler of each of
its targets. .then()
is used to create a new target signal with a
given handler function. To further propagate the value, handler functions should
use .put()
to send the value from the relevant signal (provided as the this
context) to its target signals. Once the the handler function has completed its
processing, it should tell the signal that its ready to handle the next value or
error using .next()
.
var s = sig()
var t1 = s.then(function (v) {
this.put(v + 1).next()
})
var u1 = t1.each(sig.log)
u1.done()
var t2 = s.then(function (v) {
this.put(v * 2).next()
})
var u2 = t2.each(sig.log)
u2.done()
s.put(3)
// -- s --
// | 3 | 3
// v v
// t1 t2
// | 4 | 6
// v v
// u1 u2
If any new values or errors are received before .next()
has been called, they
will get buffered, then popped off once the signal is ready to process them.
Since sychronous handlers are likely to always call .next()
at the end,
.each()
is available as a thin wrapper around .then()
that calls
.next()
itself once the given function has been called.
error handling
Errors propagate from a source signal to its target signals using
.throw()
, much in the same way values propagate with
.put()
. catch
is used to create a new target signal with a
given error handler. As is the case for value propagation, the error handler
needs to call .next()
to tell the signal to handle the next value or
error.
var s = sig()
var t1 = s.catch(function (e) {
this.throw(e).next()
})
var u1 = t1.catch(sig.log)
u1.done()
var t2 = s.catch(function (e) {
this.throw(e).next()
})
var u2 = t2.catch(sig.log)
u2.done()
s.throw(new Error('o_O'))
// ---- s ----
// | o_O | o_O
// v v
// t1 t2
// | o_O | o_O
// v v
// u1 u2
Error handler functions can also propagate values, which is useful for cases where a signal can recover from an error.
var s = sig()
s.catch(function () {
this.put(null).next()
})
.each(sig.log)
.done()
s.put(21) // 21
.throw(new Error('o_O')) // null
.put(23) // 23
If an error has put the signal into a state it cannot recover from,
.kill()
can be used to end the signal, regardless of whether there
are still values to be sent.
var s = sig()
.catch(function () {
this.kill()
})
.done()
Note that .throw()
and .catch()
should always be used as a way to propagate
and handle errors occuring in a chain of signals, as opposed to javascript's
native throw
and try
-catch
error handling, since signal processing can
occur asynchronously (depending on how sig is being used).
ending chains
Once a signal chain has been set up, and values and errors can not propagate any
further, .done()
should be used to declare the end of the signal
chain. Once the end of the signal chain is declared, the signals in the chain
are unpaused
for the first time to allow values and
errors to start propagating.
sig([23])
.each(sig.log) // (nothing has been logged yet)
.done() // 23 (the chain has been started, `23` has been logged)
If no function is given to .done()
, it will rethrow unhandled errors using
javascript's native throw
, then kill the last signal in the chain with
.kill()
.
var s = sig()
s.map(function (v) {
return v + 1
})
.filter(function (x) {
return !(x % 2)
})
.each(sig.log)
.done()
s.put(1) // 2
.put(2)
.put(3) // 4
.throw(':/') // Error: :/
.done()
accepts a node.js-style callback function. If an error reaches the end
of the signal chain, the callback function is called with the error as its first
argument, then the last signal in the chain is killed using .kill()
.
var s = sig()
s.map(function (v) {
return v + 1
})
.filter(function (x) {
return !(x % 2)
})
.each(sig.log)
.done(function (e) {
sig.log(e || 'done!')
})
s.put(1) // 2
.put(2)
.put(3) // 4
.throw(':/') // :/
.put(4)
.put(5)
If a signal in the chain has ended, the callback function is invoked without any arguments.
var s = sig()
s.map(function (v) {
return v + 1
})
.filter(function (x) {
return !(x % 2)
})
.each(sig.log)
.done(function (e) {
sig.log(e || 'done!')
})
s.put(1) // 2
.put(2)
.put(3) // 4
.end() // done!
If any values propogate to the end of the signal chain, .done()
will
discard them.
// nothing will get logged, `.done()` has discarded the values
sig([1, 2, 3]).done().each(sig.log)
disposal
When a signal is no longer needed, .end()
should be used. Ending a
signal causes the signal to end each of its targets (and in turn, each target
will end their own targets) and disconnects the signal from its
source. Once the signal no longer has buffered values that it needs to send, its
teardowns are called, its state is cleared and it is marked as
ended. Signals marked as ended treat .put()
, .throw()
and
.then()
as no-ops. The immediate disconnecting of a signal is
necessary to avoid memory leaks caused by signals with buffers that never clear.
var s = sig()
s.each(sig.log).done()
s.teardown(sig.log, 'ended').pause().put(23).end()
s.resume()
// 23
// ended
If the signal needs to be ended immediately, regardless of whether it still has
values it needs to send, kill
should be used.
var s = sig()
s.each(sig.log).done()
s.teardown(sig.log, 'ended').pause().put(23).kill() // ended
Note that creating signals without ending them when their work is done will lead to memory leaks for the same reasons not removing event listeners will when using an event listener pattern.
disconnects
When a signal is ended, the chain of signals ending with it (if any) will no longer be sending values to it, so it can be removed from the chain. However, other signals in the chain cannot be ended, as sibling targets (targets with the same source) might still be around listening for new values. To prevent chains of unused target signals being kept in memory as a result of this, source signals forget a target signal when the target no longer has its own targets, putting the target in a 'disconnected' state. Targets keep a reference to their source, so a signal chain will be reconnected if a new target gets added at the end of the chain.
var a = sig()
var b = sig()
var c = sig()
var d = sig()
var e = sig()
a.then(b)
b.then(c).done()
b.then(d).done()
// a
// |
// v
// ---- b
// | |
// v v
// c d e
c.end()
// a
// |
// v
// b
// |
// v
// c d e
d.end()
// a
//
//
// b
//
//
// c d e
b.then(e).done()
// a
// |
// v
// b ----
// |
// v
// c d e
pausing and resuming
When a signal is paused using pause
, any values given to it by
put
are buffered. When the signal is resumed using
resume
, any buffered values are sent to the signal's targets, and
any new values will be sent straight to the signal's targets (and not get
buffered).
var s = sig()
s.each(sig.log).done()
s.pause().put(21).put(23)
s.resume()
// 21
// 23
Note that signals start off paused and are unpaused for the first time either
once the end of the signal chain is declared or once
.resume()
is called explicitly.
redirection
Sometimes, a function will return a single signal, though it has created one or more signal chains to send values to the returned signal.
Redirecting using .put()
from a different signal's value handling
function will cause the signal to continue running indefinitely instead of
disconnecting with its targets:
function join(a, b) {
var out = sig()
var badRedirA = a.each(badRedir)
var badRedirB = b.each(badRedir)
function badRedir(v) {
out.put(v)
this.next()
}
return out
}
var a = sig()
var b = sig()
var out = join(a, b)
var logOut = out.each(sig.log)
logOut.done()
// single line for targets, double line for redirections
//
// a b
// | |
// v v
// badRedirA ==> out <== badRedirB
// |
// v
// logOut
a.put(21) // 21
b.put(23) // 23
out.end()
// redirA and redirB are still connected :/
//
// a b
// | |
// v v
// redirA ==> out <== redirB
//
//
// logOut
To redirect without this unwanted behaviour, .to()
should be used to
redirect values and errors to the returned signal, and to set these chains to
disconnect when the returned signal is disconnected.
If a function creates a signal chain, but the chain isn't returned, redirected or ended, this will lead to memory leaks. Rule of thumb: If you have a signal that outputs values, either return the signal, or redirect it to another returned signal.
function join(a, b) {
var out = sig()
var redirA = a.to(out)
var redirB = b.to(out)
return out
}
var a = sig()
var b = sig()
var out = join(a, b)
var logOut = out.each(sig.log)
logOut.done()
// single line for targets, double line for redirections
//
// a b
// | |
// v v
// redirA ==> out <== redirB
// |
// v
// logOut
a.put(21) // 21
b.put(23) // 23
out.end()
// redirA and redirB are disconnected!
//
// a b
//
//
// redirA out redirB
//
//
// logOut
Note that .to()
calls .done()
. This means calling
.to()
declares the end of a signal chain and starts the signal chain,
and .done()
does not need to be called on redirected chains.
sticky signals
Sometimes, a signal needs to hold onto the last value it has sent out. When new targets arrive, they need to receive this last value instead of having them 'miss the bus' and only receive new values sent from the source signal. Sticky signals allow this.
Sticky signals can be created using val
.
var v = sig.val(23)
v.each(sig.log) // 23
v.each(sig.log) // 23
api
sig([values])
Creates a new signal. If a values
array is given, it is used as the initial
values sent from the signal.
var s = sig([1, 2, 3])
functions and methods
The following sig methods are also accessible as static functions taking a signal as the first argument:
put
, then
, done
, next
, end
, kill
, resolve
, putTo
, putEach
,
throw
, catch
, teardown
, pause
, resume
, map
, each
, tap
, filter
,
flatten
, limit
, once
, then
, to
, redir
, update
, append
, call
,
event
For example, using the static counterpart of .put
would look something
like:
var s = sig()
s.each(sig.log).done()
sig.put(s, 21) // 21
sig.put(s, 23) // 23
event catalogue
disconnect
Emitted when a connected signal disconnects.
reconnect
Emitted when a disconnected signal reconnects.
flush
Emitted after a signal has propagated any buffered values or errors, if any, after being resumed.
end
Emitted once a signal is about to end, before the signal clears its state and gets marked as ended. See disposal.
ending
Emitted once a signal has been scheduled to end via .end() or .kill(). See disposal.
.put([v])
Puts the value v
through the signal, where v
can be a value of any type.
var s = sig()
s.each(sig.log).done()
s.put(21) // 21
.put(21) // 23
.next()
Tells the calling signal that it is done processing its most recent value or error, if any, and is ready to processing the next value or error.
var s = sig()
var t = s.then(sig.log)
t.done()
s.put(1) // 1
.put(2)
t.next() // 2
.throw(e)
Propogates the error instance e
from the signal.
var s = sig()
s.catch(sig.log).done()
s.throw(new Error('o_O')) // o_O
.end()
Ends the given signal, causing it to end its target signals and disconnect from its source, then clear its state once the signal no longer has values to send. See disposal.
var s = sig()
s.each(sig.log).done()
s.put(21) // 21
.end()
.put(23)
.kill()
Ends the given signal immediately, regardless of whether the signal still has values it needs to send. See disposal.
sig().teardown(sig.log, 'Ended').end().kill() // Ended
.then(fn[, args...])
Creates and returns a new target signal with fn
as its value handler. fn
is
called with each received value as its first argument and the created signal as
its this
context. The target signal is returned to allow for further signal
chaining.
var s = sig()
s.then(function (v) {
this.put(v + 2).next()
})
.each(sig.log)
.done()
s.put(21) // 23
If extra arguments are provided, they are used as extra arguments to each call
to fn
.
var s = sig()
s.then(
function (a, b, c) {
this.put(a + b + c).next()
},
1,
2
)
.each(sig.log)
.done()
s.put(20) // 23
.then(t)
Sets the calling signal as the source of the signal t
and returns t
.
var s = sig()
var t = s.then(sig())
t.each(sig.log).done()
s.put(23) // 23
.done([fn])
Ends a chain of signals (see ending chains). If an unhandled
error reaches the end of the signal chain fn
will be called with the error as
its first argument and the last signal in the chain will be killed. If
the signal ends without any errors fn
will be called with no arguments. If
fn
isn't given, the first unhandled error will be rethrown using javascript's
native throw
.
var s = sig()
s.map(function (v) {
return v + 1
})
.filter(function (x) {
return !(x % 2)
})
.each(sig.log)
.done(function (e) {
sig.log(e || 'done!')
})
s.put(1) // 2
.put(2)
.put(3) // 4
.throw(':/') // :/
.put(4)
.put(5)
.resume()
Resumes the signal, causing the buffered values to propagate to the signal's targets and causing any new values to be sent to the signal's targets.
var s = sig()
s.each(sig.log).done()
s.put(21) // 21
.pause()
.put(23)
.resume() // 23
.catch(fn[, args...])
Creates and returns a new target signal with fn
set as its error handler. fn
is called with each thrown error as its first argument and the created signal as
its this
context. The created signal is returned to allow for further signal
chaining.
var s = sig()
s.catch(function (e) {
sig.log(e)
this.next()
}).done()
s.throw(new Error('o_O')) // o_O
If extra arguments are provided, they are used as extra arguments to each call
to fn
.
var s = sig()
s.catch(function (a, b, c) {
sig.log(a, b, c)
this.next()
}).done()
s.throw(new Error('o_O'), '-_-', ':/') // o_O -_- :/
.each(fn[, args...])
Creates and returns a new target signal with a value handler that calls fn
,
then calls .next()
immediately afterwards. This is useful for
synchronous signals, where the value handler will almost always end with
.next()
. The target signal is returned to allow for further signal chaining.
fn
is called with each received value as its first argument and the created
signal as its this
context.
var s = sig()
s.each(function (v) {
this.put(v + 2)
})
.each(sig.log)
.done()
s.put(21) // 23
Note that if the handler is doing asynchronous work, it would make more sense to
use .then
, then call .next()
when the asynchronous work
completes.
If extra arguments are provided, they are used as extra arguments to each call
to fn
.
var s = sig()
s.each(
function (a, b, c) {
this.put(a + b + c)
},
1,
2
)
.each(sig.log)
.done()
s.put(20) // 23
Since .each()
is intended for use with synchronous functions, if fn
throws
an error using javascript's native throw
, the error will be caught and as an
error in the signal chain.
.tap(fn[, args...])
Creates and returns a new target signal with a value handler that calls fn
,
then propogates the received value unchanged, allowing a function to 'tap' into
a signal chain.
var s = sig()
s.map(function (v) {
return v + 1
})
.tap(sig.log)
.filter(function (v) {
return !(v % 2)
})
.done()
s.put(21) // 22
.put(22) // 23
.put(23) // 24
.map(fn[, args...])
Creates and returns a new target signal with a value handler that calls fn
and
outputs its return value. fn
is called with each received value as its first
argument and the created signal as its this
context.
var s = sig()
s.map(function (v) {
return v + 2
})
.each(sig.log)
.done()
s.put(21) // 23
If extra arguments are provided, they are used as extra arguments to each call
to fn
.
var s = sig()
s.map(
function (a, b, c) {
this.put(a + b + c)
},
1,
2
)
.each(sig.log)
.done()
s.put(20) // 23
.map(v)
Creates and returns a new signal with a value handler that simply outputs v
for every value received by the signal. The created signal uses s
as its
source signal. fn
is called with each received value as its first argument and
the created signal as its this
context.
var s = sig()
s.map(function (v) {
return v + 2
})
.each(sig.log)
.done()
s.put(21) // 23
If extra arguments are provided, they are used as extra arguments to each call
to fn
.
var s = sig()
s.map(
function (a, b, c) {
this.put(a + b + c)
},
1,
2
)
.each(sig.log)
.done()
s.put(20) // 23
.filter([fn[, args...]])
Creates and returns a new taret signal with a value handler that calls fn
to
determine whether to output a recieved value. fn
is called with each received
value as its first argument and the created signal as its this
context.
var s = sig()
s.filter(function (v) {
return v % 2
})
.each(sig.log)
.done()
s.put(22).put(23) // 23
If extra arguments are provided, they are used as extra arguments to each call
to fn
.
var s = sig()
s.filter(
function (a, b, c) {
return (a + b + c) % 2
},
1,
2
)
.each(sig.log)
.done()
s.put(22) // 22
.put(23)
If fn
isn't provided, an identity function is used, filtering values based on
their truthyness.
var s = sig()
s.filter().each(sig.log).done()
s.put(0).put(1) // 1
.to(t)
Redirects values and errors sent from the calling signal to signal t
. The
returned signal is a new signal that controls this redirection. When either it,
s
or t
are ended, the redirection ends. to
behaves differently to then
,
as it does not set the calling signal as the source of t
.
function join(a, b) {
var out = sig()
a.to(out)
b.to(out)
return out
}
var a = sig()
var b = sig()
join(a, b).each(sig.log).done()
a.put(21) // 21
b.put(23) // 23
.redir(t)
Alias for .to()
.
function join(a, b) {
var out = sig()
a.redir(out)
b.redir(out)
return out
}
var a = sig()
var b = sig()
join(a, b).each(sig.log).done()
a.put(21) // 21
b.put(23) // 23
.tap(t)
Redirects values propagated by the calling signal to another signal t
and
returns a new signal that propagates the source signal's values unchanged. This
allows a signal to 'tap' into another signal chain. Note that unlike
.to()
, .tap()
does not implicately declare the end of a signal chain
with .done()
.
var s = sig()
var t = sig()
t.each(sig.log).done()
s.map(function (v) {
return v + 1
})
.tap(t)
.filter(function (v) {
return !(v % 2)
})
.done()
s.put(21) // 22
.put(22) // 23
.put(23) // 24
Redirection will stop when t
disconnects, when the returned signal disconnects
or when the source signal disconnects. When t
disconnects, the returned signal
will continue to propagate the source signal's values.
.flatten()
Creates and returns a new target signal that outputs each non-array value in a series of possibly nested arrays.
var s = sig()
s.flatten().each(sig.log).done()
s.putEach([1, [2, [3, [4, 5, [6, 7, 8, [9, [10]]]]]]])
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.limit(n)
Creates and returns a new target signal that only propogates the first n
values it receives.
var s = sig()
s.limit(3).each(sig.log).done()
s.put(21) // 21
.put(22) // 22
.put(23) // 23
.put(24)
.put(25)
.once()
Special case of limit
where n === 1
.
var s = sig()
s.once().each(sig.log).done()
s.put(21) // 21
.put(22)
.put(23)
.update(fn[, args...])
Returns a new target signal that 'updates' to proxy the signal most recently
generated by a function fn
mapping the calling signal's output values.
var s = sig()
var lookup = {
t: sig()
u: sig()
}
s.update(function(k) { return lookup[k] })
.each(sig.log)
.done()
s.put('t')
lookup.t
.put(1) // 1
.put(2) // 2
.put(3) // 3
s.put('u')
lookup.u
.put(4) // 4
.put(5) // 5
.put(6) // 6
lookup.t
.put(7)
.put(8)
.put(9)
If fn
returns a non-signal, its result is ignored.
If fn
isn't given, an identity function is used as the default. This can be
useful for turning a signal of signals into a single signal.
var s = sig()
var t = sig()
var u = sig()
s.update().each(sig.log).done()
s.put(t)
t.put(1) // 1
.put(2) // 2
.put(3) // 3
s.put(u)
u.put(4) // 4
.put(5) // 5
.put(6) // 6
t.put(7).put(8).put(9)
.append(fn[, args...])
Returns a new target signal that proxies every signal generated by a function
fn
mapping the calling signal's output values. Each time a new signal is
generated, it is 'appended' to the signals being tracked, so outputs of previous
signals will still be proxied when a new signal is generated by fn
.
var s = sig()
var lookup = {
t: sig()
u: sig()
}
s.append(function(k) { return lookup[k] })
.each(sig.log)
.done()
s.put('t')
lookup.t
.put(1) // 1
.put(2) // 2
.put(3) // 3
s.put('u')
lookup.u
.put(4) // 4
.put(5) // 5
.put(6) // 6
lookup.t
.put(7) // 7
.put(8) // 8
.put(9) // 9
If fn
returns a non-signal, its result is ignored.
If fn
isn't given, an identity function is used as the default. This can be
useful for turning a signal of signals into a single signal.
var s = sig()
var t = sig()
var u = sig()
s.append().each(sig.log).done()
s.put(t)
t.put(1) // 1
.put(2) // 2
.put(3) // 3
s.put(u)
u.put(4) // 4
.put(5) // 5
.put(6) // 6
t.put(7) // 7
.put(8) // 8
.put(9) // 9
.call(fn[, args...])
Calls a function fn
with the calling signal as its first argument and args
as the remaining arguments. Useful for hooking custom functions into a signal
chain.
var s = sig()
s.call(mul, 2).each(sig.log).done()
s.putEach([1, 2, 3])
// [2, 4, 6]
function mul(s, n) {
return s.map(function (v) {
return v * n
})
}
.event(name)
Returns a new signal that propagates each event with the given name
emitted by
the signal. See the event catalogue for the events emitted
by the signal.
var s = sig()
s.event('flush')
.each(function () {
sig.log('flush!')
})
.done()
s.pause()
.resume() // flush!
.pause()
.resume() // flush!
.teardown(fn[, args...])
Schedules fn
to be called when the calling signal has ended. fn
is called
with the calling signal as its this
context. Any state used by the signal
should be deconstructed inside a teardown function. If the calling signal has
already ended, fn
is called immediately. See disposal.
function tick() {
var s = sig()
var id = setInterval(resolve, 200, s)
s.teardown(function () {
clearInterval(id)
})
return s
}
var s = tick()
s.each(sig.log).done()
// this will cause the teardown function to get called
s.end()
.resolve([v])
Sends the value v
(or undefined
if no value is given) from the calling
signal, then ends the signal.
var s = sig()
s.each(sig.log).done()
s.resolve(21) // 21
.put(23)
.putEach()
Sends each value in a values
array from the calling signal.
var s = sig()
s.each(sig.log).done()
s.putEach([1, 2, 3])
// 1
// 2
// 3
.putTo(t)
Sends the signal as a value to signal t
.
var s = sig()
s.update().each(sig.log).done()
var t = sig()
t.putTo(s).put(23) // 23
sig.val([v])
Creates and returns a new sticky signal. If v
is given, it is used
as the initial value for the created signal.
var v = sig.val(23)
v.each(sig.log).done() // 23
v.each(sig.log).done() // 23
sig.ensureVal(v)
If a v
is given, a sticky signal is returned with v
as its initial value. If
v
is a signal, a new sticky signal is returned with v
as its source.
var v = sig.ensureVal(23)
v.each(sig.log).done() // 23
var s = sig()
var t = sig.ensureVal(s)
s.put(23)
t.each(sig.log).done() // 23
t.each(sig.log).done() // 23
sig.any(values)
Accepts an array of values
, where each value can be either a signal or
non-signal, and returns a signal that outputs an array containing the value and
its corresponding signal's index in the array whenever one of the signals in the
array changes.
var s = sig()
var t = sig()
sig.any([s, 23, t]).each(sig.spread, sig.log).done()
s.put(1) // 1 0
t.put(3) // 3 2
s.put(2) // 2 0
t.put(1) // 1 2
s.put(3) // 3 0
sig.any(obj)
Identical to sig.any(values)
, except it handles an object of
key-value pairs instead of an array, where each value can be either a signal or
non-signal. The values outputted from the signal are arrays, each containing the
given value and its corresponding signal's key in the object.
var s = sig()
var t = sig()
sig
.any({
a: s,
b: 23,
c: t
})
.each(sig.spread, sig.log)
.done()
s.put(1) // 1 a
t.put(3) // 3 c
s.put(2) // 2 a
t.put(1) // 1 c
s.put(3) // 3 a
sig.all(values)
Accepts an array of values
, where each value can be either a signal or
non-signal, and returns a signal that outputs an array of the current values of
each signal and non-signal each time one of the values changes. Note that the
returned signal will only start outputting once each signal in the array has put
through its first value.
var s = sig()
var t = sig()
sig.all([s, 23, t]).each(sig.log).done()
s.put(1)
t.put(3) // [1, 23, 3]
s.put(2) // [2, 23, 3]
t.put(1) // [2, 23, 1]
s.put(3) // [3, 23, 1]
sig.all(obj)
Identical to sig.all(values)
, catch it handles an object of
key-value pairs instead of an array, where each value can be either a signal or
non-signal.
var s = sig()
var t = sig()
sig
.all({
a: s,
b: 23,
c: t
})
.each(sig.log)
.done()
s.put(1)
t.put(3)
// {
// a: 1,
// b: 23,
// c: 3
// }
s.put(2)
// {
// a: 2,
// b: 23,
// c: 3
// }
t.put(1)
// {
// a: 2,
// b: 23,
// c: 1
// }
s.put(3)
// {
// a: 3,
// b: 23,
// c: 1
// }
sig.merge(values)
Accepts an array of values
, where each value can be either a signal or
non-signal, and returns a signal that outputs the values put through each signal
in the array.
var s = sig()
var t = sig()
sig.merge([s, 23, t]).each(sig.log).done()
s.put(1) // 1
t.put(3) // 3
s.put(2) // 2
t.put(1) // 1
s.put(3) // 3
sig.merge(obj)
Identical to sig.merge(values)
, except it handles an object
of key-value pairs instead of an array, where each value can be either a signal
or non-signal. The values outputted from the signal are the values sent from
each signal in the object.
var s = sig()
var t = sig()
sig
.merge({
a: s,
b: 23,
c: t
})
.each(sig.log)
.done()
s.put(1) // 1
t.put(3) // 3
s.put(2) // 2
t.put(1) // 1
s.put(3) // 3
sig.isSig(v)
Returns true
if v
is a signal, false
if it is not.
sig.isSig(23) // => false
sig.isSig(sig()) // => true
sig.log(v)
Logs the given arguments. Similar to console.log
, except it does not rely on
console
as its this
context and returns its first argument.
var s = sig()
s.filter()
.map(sig.log)
.map(function (v) {
return v * 2
})
.each(sig.log)
.done()
s.putEach([0, 1, 1, 0])
// 1
// 1
// 2
// 2
sig.putTo(v, s)
The static form of .putTo()
, except v
can be a value of any time
(it does not have to be a signal).
install
You can use this library as the npm package sig-js
:
npm i sig-js
# or
yarn add sig-js
It can be used in both es-module-aware and commonjs bundlers/environments.
// es module
import sig from 'sig-js'
// commonjs
const sig = require('sig-js')
It can also be used a <script>
:
<script crossorigin src="https://unpkg.com/sig-js/dist/umd/sig.js"></script>
<script>
sig()
</script>