(function () {
"use strict";
Class('signals.PromiseSignal', { Extends: signals.Signal,
_originalDispatchMethod: null,
/**
*
* @class signals.PromiseSignal
*
* @classdesc
* PromiseSignal extends the Signal class to return a new promise
* for every dispatch call. The promise *fulfill* and *reject* methods
* are given to all signal listeners so that any listener can fulfill
* or reject the promise.
*
* This is pretty awesome for decoupled systems that talk via signals
* and commands. With the promises there is now an informal approach
* for a command to give an answer about the result of the operation.
*
* The code that dispatches the signal (and possibly triggers some
* other action somewhere in the system) often wants to know if the
* triggered operation was successful or not.
*
* @initialize
* The PromiseSignal constructor does not take any parameters.
*
* @example
* <caption>
* <h4>Creating and Using a PromiseSignal</h4>
* This example shows how to setup a PromiseSignal
* that has one listener which fulfills the promise
* immediately. The fulfillment listener is invoked
* because it was registered as first argument to the
* dispatch(…).then() method of the promise.
* </caption>
*
* var promiseSignal = new signals.PromiseSignal(),
* fulfillData = {},
* dispatchData = {};
*
* function signalListener(data, promise) {
*
* expect.equal(data, dispatchData, 'Expected to receive dispatched data')
*
* // here the listener fulfills the promise!
* promise.fulfill(fulfillData);
* }
*
* // when the listener fulfills the promise this function is called
* function promiseFulfilledListener(data) {
* expect.equal(data, fulfillData, 'Expected fulfill data');
* }
*
* promiseSignal.add(signalListener);
* promiseSignal.dispatch(dispatchData).then(promiseFulfilledListener);
*
* @memberof! <global>
*/
Constructor: function() {
// let super class construct this signal
this.Class.Super.apply(this, arguments);
// save reference to original dispatch of signals.Signal
this._originalDispatchMethod = this.dispatch;
// replace the original dispatch method by our wrapper
this.dispatch = this.Class.prototype.dispatch;
},
/**
* Dispatches the signal like the base class but returns
* a new promise object and provides all listeners with
* the promise *fulfill* and *reject* functions.
*
* @param {*} any data that should be dispatched to the listeners
*
* @returns {Promise} A Promise A/+ instance
*
* @memberof signals.PromiseSignal#
*/
dispatch: function() {
var argumentsArray = Array.prototype.slice.call(arguments),
This = this;
return new Promise(function(fulfill, reject) {
if(This.getNumListeners() == 0) {
fulfill();
}
else {
argumentsArray.push({
fulfill: fulfill,
reject: reject
});
// call the original dispatch method with the promise
This._originalDispatchMethod.apply(This, argumentsArray);
}
});
}
});
}());