Reputation: 57254
I have several different JavaScript objects with methods that i want to keep separate. However, I need some type of observer, callback, or plugin design so that I can trigger these methods at the correct time.
For example, A.Foo()
should almost always run after B.Bar()
- but I do not want to place a call to A.Foo()
inside B.Bar()
because there are those odd times it should not run after B.Bar()
. That would be coupling my code and I know that's bad.
I want to approach this problem as if B.Bar()
is just doing it's job and does not ever plan on knowing about A.Foo()
or any other function that might want to tag along with it. In other words, plugin support for future developers.
How do you design modular, non-coupled code with observer or event based callbacks in Javascript?
Upvotes: 3
Views: 1160
Reputation: 4074
Dojo allows you to listen to function calls.
dojo.connect("foo", A, function(){
B.bar();
});
Upvotes: 0
Reputation: 10712
It depends whether your scenario is really event like in nature, or more of an asynchronous operation:
Using something like microevent you could do the following. This pattern is really common and simple, so I suggest that at some point you have a go at implimenting this yourself, as it's great from an understanding point of view.
MicroEvent.mixin(A);
A.Foo = function () {
//Do stuff A needs to do, then:
A.trigger('foo-complete');
};
//Somewhere nice and separate and decoupled
A.bind('foo-complete', B.Bar);
If you need to do more complex things like filter the events, map the events etc. Reactive Extensions (which are based of the C# libraries) are really powerful, but that's a big library to load in if you don't need the functionality.
This can be done using callbacks, which is great for fairly simple operations:
A.Foo = function (cb) {
//Do stuff A needs to do, then:
if (cb) cb();
};
A.Foo(B.Bar);
These initially look more complicated, but they are easilly composable, and have nice ways of handling errors built in.
Using Q which is one of the more popular promise libraries (again, there are loads of these):
A.Foo = function () {
var def = Q.defer();
setTimeout(function () {
//Simulate async operation
def.resolve();
}, 1000);
return def.promise;
};
A.Foo().then(B.Bar).end();
Control flow libraries (arguably promises are a special case of this) aim to help you compose operations that are based on the callback system.
Upvotes: 2