schlomix-node
v0.0.9
Published
**schlomix** is the collection of everything I experiment and tinker with. Some of it turns out to be quite useful and may end up as part of its own package. Feel free to use as you see fit.
Downloads
12
Readme
schlomix is the collection of everything I experiment and tinker with. Some of it turns out to be quite useful and may end up as part of its own package. Feel free to use as you see fit.
This will continue to grow as I add more.
Changes in v.0.0.7
- Rewrote everything in TypeScript as a learning exercise
- Added a gulp build file
Signals
Signals are simplified event emitters - They only emit one event. They are inspired by Slot/Signal mechanisms from GUI toolkits, such as Qt or GTK+.
Signal exposes only two methods (not counting the additional methods inherited by EventEmitter.)
- connect()
- emit()
Connect has the signature:
(method: Function, scope?: Object) => Signal
It returns itself, for chaining (albeit the usefulness of this is debatable, only given two methods...) At this time, disconnecting is not available.
The first argument, method is the function that will be invoked when the Signal is emitted. scope is (of course) optional. If provided, the this keyword will be bound to scope inside method.
The arguments passed to emit() will be passed directly into method, so for example:
var sig = new Signal();
sig.connect(function (a, b, c) {
console.log(c, b, a);
});
sig.emit(1,2,3); // On the console: 3 2 1
Using Scope in Signals
If you specify a scope the this keyword will be available inside method. This is useful when using instance methods as callbacks:
function Droid (name) {
this.name = name;
this.radio = new Signal();
this.radio.connect(this.onGivenTask, this);
}
Droid.prototype.giveTask = function (task) {
this.radio.emit(task);
};
Droid.prototype.onGivenTask = function (task) {
console.log(this.name + ' is doing: ' + task);
};
var astromech = new Droid('R2D2');
astromech.giveTask('Shut down all the garbage smashers on the detention level!');
Futures
Futures are a type of a promise, allowing the user to handle various states of asyncronous calls, without disrupting [too much] the program flow. They are similar to Signals, in that, they are a simplified EventEmitter, but unlike Signals, they only fire once and then are automatically disposed.
The class Future exposes 5 methods:
- onSuccess()
- onFail()
- onFinally()
- accept()
- reject()
The first three, onSuccess, onFail, onFinally allow an interested user to be notified when a Future is either accepted or rejected. Finally is always invoked after the Future has been accepted or rejected. The last two, accept and reject trigger the Future to notify all interested parties.
The three wiring methods have the signature:
(method: Function, scope?: Object) => Future
Similar to Signal, the method is the callback that will be invoked, and scope is the optional this binding. They all return the Future for chaining. This allows a user to wire up all three event callbacks in one swift motion:
var future = new Future();
future.onSuccess(function () { ... }).onFail(function () { ... }).onFinally(function () { ... });
accept() has the signature:
(...args) => void
reject() has the signature:
(err: Error|Any) => void
accept() will trigger all of the wired onSuccess callbacks, passing in the arguments exactly as they were passed to accept()
var future = new Future();
future.onSuccess(function (a, b, c) {
console.log(c, b, a);
}).onSuccess(function (d, e, f) {
console.log(d + e + f);
});
future.accept(1,2,3);
// console output:
// 3, 2, 1
// 6
reject() will trigger all of the wired onFail callbacks, passing along the error argument. (It does not have to be an instance of Error, but this is a useful way to bubble up Errors and Exceptions from inside asyncronous calls.)
var future = new Future();
future.onFail(function (err) {
console.log(err.message);
});
future.reject(new Error('Oh noes!'));
// console output:
// Oh noes!
And finally, wired onFinally callbacks are invoked after a Future has been accepted or rejected. It takes no arguments and is useful for doing any cleanup work post state handling.
var future = new Future();
var someScope = {
cleanup: function () {
console.log('doing some cleanup');
}
};
future.onFinally(function () {
this.cleanup();
}, someScope);
future.accept('all done');
// console output:
// doing some cleanup
The second argument to onSuccess, onFail, and onFinally is the scope binding, and can be bound to any object, as we see in this last onFinally example.
Bringing It All Together
*** Full Future Example ***
function doAjax() {
var future = new Future();
$.ajax('/some_url', { ... })
.done(function (response) {
var someProcessedData = processResponse(response);
future.accept(someProcessedData);
})
.fail(function (errResponse) {
// do some work on errResponse if necessary
future.reject(errResponse);
});
return future;
}
var timer = new Timer();
timer.start();
doAjax().onSuccess(function (processedData) {
// do something with processed data
}).onFail(function (err) {
// handle error
}).onFinally(function () {
timer.stop();
console.log(timer.getTime());
});