-
Notifications
You must be signed in to change notification settings - Fork 4
Signal and pump
What if human's input are the async action we want to deal with? for example you want to validate a form with different conditions, and the form will pass validation only when each field passed. Unlike most async solutions which are focus on data processing, Action
have a very elegant solution to that a problem too:
var Action.signal = new Action(function(cb){
return cb;
})
This's the core of a signal, it's a special Action
which never call the cb
, instead it return cb
directly. What does that suppose to mean?
var logSignal = Action.signal
.guard(function(err){
console.log(err.message);
return false;
})
.next(function(data){
console.log(data);
return true;
});
var logPump = logSignal.go()
Make sure you read Return value of go before! we use pump to mark the return value of firing a signal. It's easy to see logPump
above is just a function composed by guard
and next
, it's equivalent to:
function(data){
if (data instance of Error){
console.log(err.message);
return false;
} else {
console.log(data);
return true;
}
}
Here we skip the instanceof Action
stuff, actually you can return an Action
inside next
and guard
, because a signal is just an Action
, any Action
s can be easily composed into a signal. Now you can pump a value to the signal using logPump
anywhere you want:
logPump('hello world')
// hello world
logPump(new Error('damn'))
// damn
If you want to sent a value to backend to do validation, just wrap the validation inside an Action
like this:
var logSignal = Action.signal
.next(function(data){
return someAsyncValidation(data);
// this should be a Action
}
.next(function(data){
console.log('The validation result is:' + data);
});
The intereting thing about signal is that, it's an Action
never fired unless we pump something into it, so it gives controll back to us, it can be fired multiple times, so we have some special combinators for signals:
var pumps = Action.fuseSignal([ logSignal, logSignal ])
.next(function(data){
console.log(data[0], data[1]);
})
.go()
setTimeout(pumps[0], 100, 'foo');
setTimeout(pumps[1], 1000, 'bar');
// after 100ms, 'foo' will be logged.
// after 1000ms, 'bar' will be logged.
// after 'bar' was logged, true, true will also be logged.
setTimeout(pumps[1], 2000, 'bar');
// true, true
setTimeout(pumps[1], 3000, new Error 'testError');
// true, false
This combinator combine an Array of signals into one, and you got a pumps array using go
, now only if you pumped all the pumps, the composed signal will be pumped. It's different to Action.all
in that since user now have full controll of pumps, fused signal will be pumped everytime if you continue pumping value into it after all pumps have been pumped.