Dispatcher
Dispatcher is used to broadcast payloads to registered callbacks. This is different from generic pub-sub systems in two ways:
- Callbacks are not subscribed to particular events. Every payload is dispatched to every registered callback.
- Callbacks can be deferred in whole or part until other callbacks have been executed.
Check out Dispatcher.js for the source code.
API
register(function callback): string
Registers a callback to be invoked with every dispatched payload. Returns a token that can be used withwaitFor()
.unregister(string id): void
Removes a callback based on its token.waitFor(array<string> ids): void
Waits for the callbacks specified to be invoked before continuing execution of the current callback. This method should only be used by a callback in response to a dispatched payload.dispatch(object payload): void
Dispatches a payload to all registered callbacks.isDispatching(): boolean
Is this Dispatcher currently dispatching.
Example
For example, consider this hypothetical flight destination form, which selects a default city when a country is selected:
var flightDispatcher = new Dispatcher();
// Keeps track of which country is selected
var CountryStore = {country: null};
// Keeps track of which city is selected
var CityStore = {city: null};
// Keeps track of the base flight price of the selected city
var FlightPriceStore = {price: null};
When a user changes the selected city, we dispatch the payload:
flightDispatcher.dispatch({
actionType: 'city-update',
selectedCity: 'paris',
});
This payload is digested by CityStore
:
flightDispatcher.register(function (payload) {
if (payload.actionType === 'city-update') {
CityStore.city = payload.selectedCity;
}
});
When the user selects a country, we dispatch the payload:
flightDispatcher.dispatch({
actionType: 'country-update',
selectedCountry: 'australia',
});
This payload is digested by both stores:
CountryStore.dispatchToken = flightDispatcher.register(function (payload) {
if (payload.actionType === 'country-update') {
CountryStore.country = payload.selectedCountry;
}
});
When the callback to update CountryStore
is registered, we save a reference to the returned token. Using this token with waitFor()
, we can guarantee that CountryStore
is updated before the callback that updates CityStore
needs to query its data.
CityStore.dispatchToken = flightDispatcher.register(function (payload) {
if (payload.actionType === 'country-update') {
// `CountryStore.country` may not be updated.
flightDispatcher.waitFor([CountryStore.dispatchToken]);
// `CountryStore.country` is now guaranteed to be updated.
// Select the default city for the new country
CityStore.city = getDefaultCityForCountry(CountryStore.country);
}
});
The usage of waitFor()
can be chained, for example:
FlightPriceStore.dispatchToken = flightDispatcher.register(function (payload) {
switch (payload.actionType) {
case 'country-update':
case 'city-update':
flightDispatcher.waitFor([CityStore.dispatchToken]);
FlightPriceStore.price = getFlightPriceStore(
CountryStore.country,
CityStore.city,
);
break;
}
});
The country-update
payload will be guaranteed to invoke the stores' registered callbacks in order: CountryStore
, CityStore
, then FlightPriceStore
.