/**
* @module proact-core
*/
/**
* <p>
* `ProAct.Actor` is the basic observer-observable functionallity in ProAct.js
* </p>
* <p>
* The actors in ProAct.js form the dependency graph.
* If some actor listens to changes from another - it depends on it.
* </p>
* <p>
* The actors can transform the values or events incoming to them.
* </p>
* <p>
* Every actor can have a parent actor, that will be notified for all the changes
* on the child-actor, it is something as special observer.
* </p>
* <p>
* ProAct.Actor is part of the core module of ProAct.js.
System.out.println();
* </p>
*
* @class ProAct.Actor
* @constructor
* @param {String} [queueName]
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* <p>
* If this parameter is not a string it is used as the
* <i>transforms</i>.
* </p>
* @param {Array} [transforms]
* A list of transformation to be used on all incoming chages.
*/
function Actor (queueName, transforms) {
if (queueName && !P.U.isString(queueName)) {
transforms = queueName;
queueName = null;
}
P.U.defValProp(this, 'listeners', false, false, true, this.defaultListeners());
P.U.defValProp(this, 'listener', false, false, true, null);
P.U.defValProp(this, 'errListener', false, false, true, null);
P.U.defValProp(this, 'closeListener', false, false, true, null);
P.U.defValProp(this, 'parent', false, false, true, null);
P.U.defValProp(this, 'queueName', false, false, false, queueName);
P.U.defValProp(this, 'transforms', false, false, true,
(transforms ? transforms : []));
P.U.defValProp(this, 'state', false, false, true, P.States.init);
this.init();
}
ProAct.Actor = P.Pro = Actor;
P.U.ex(P.Actor, {
/**
* A constant defining bad values or bad events.
*
* Part of the filtering mechainsm; If a transformation returns
* a `BadValue`, based on uncomming event -> the event is skipped.
*
* @property BadValue
* @type Object
* @final
* @static
* @for ProAct.Actor
*/
BadValue: {},
/**
* A constant defining closing or ending events.
*
* If a transformation returns this value, the actor will be closed.
*
* You can manually close `Actor`s updating them with this constant as an event.
*
* @property Close
* @type Object
* @final
* @static
* @for ProAct.Actor
*/
Close: {},
/**
* Transforms the passed <i>val</i> using the {{#crossLink "ProAct.Actor/transforms:method"}}{{/crossLink}} method of the passed <i>actor</i>.
*
* @method transforms
* @for ProAct.Actor
* @static
* @param {ProAct.Actor} actor The `ProAct.Actor` which transformations should be used.
* @param {Object} val The value to transform.
* @return {Object} The transformed value.
*/
transform: function (actor, val) {
var i, t = actor.transforms, ln = t.length;
for (i = 0; i < ln; i++) {
val = t[i].call(actor, val);
if (val === P.Actor.BadValue) {
break;
}
if (val === P.Actor.Close) {
break;
}
}
return val;
}
});
P.Actor.prototype = {
/**
* Reference to the constructor of this object.
*
* @property constructor
* @type ProAct.Actor
* @final
* @for ProAct.Actor
*/
constructor: ProAct.Actor,
/**
* Initializes this actor.
* <p>
* This method logic is run only if the current state of <i>this</i> is
* {{#crossLink "ProAct.States/init:property"}}{{/crossLink}}.
* </p>
* <p>
* Then {{#crossLink "ProAct.Actor/afterInit:method"}}{{/crossLink}} is called to finish the initialization.
* </p>
*
* @for ProAct.Actor
* @instance
* @method init
*/
init: function () {
if (this.state !== P.States.init) {
return;
}
this.doInit();
this.afterInit();
},
/**
* Allocating of resources or initializing is done here.
* <p>
* Empty by default.
* </p>
*
* @for ProAct.Actor
* @instance
* @protected
* @method doInit
*/
doInit: function () {},
/**
* Called automatically after initialization of this actor.
* <p>
* By default it changes the state of <i>this</i> to {{#crossLink "ProAct.States/ready:property"}}{{/crossLink}}.
* </p>
* <p>
* It can be overridden to define more complex initialization logic.
* </p>
*
* @for ProAct.Actor
* @instance
* @protected
* @method afterInit
*/
afterInit: function () {
this.state = P.States.ready;
},
/**
* Closes this actor => it state becomes {{#crossLink "ProAct.States/closed:property"}}{{/crossLink}}.
*
* This sends a `close` event to all the subscribers to closing.
*
* After closing the actor it can't emit events anymore.
*
* Example:
* ```
* var actor = new ProAct.Actor();
* actor.onClose(function () {
* console.log('Done!');
* });
*
* actor.close(); // We will see 'Done!' on the console output.
* ```
*
* @for ProAct.Actor
* @instance
* @method close
* @return {ProAct.Actor} This instance - can be chained.
*/
close: function () {
if (this.state === P.States.closed) {
return;
}
return ActorUtil.update.call(this, P.Actor.Close, 'close');
},
/**
* Checks if <i>this</i> can be closed.
* <p>
* Defaults to return true.
* </p>
*
* @for ProAct.Actor
* @protected
* @instance
* @method canClose
*/
canClose: function () {
return true;
},
/**
* This method is called when a `close` event is pushed to this `Actor`.
*
* It removes all the subscriptions to the `Actor` and sets its
* state to {{#crossLink "ProAct.States/closed:property"}}{{/crossLink}}.
*
* Do not call this method; it is private!
*
* @for ProAct.Actor
* @private
* @instance
* @protected
* @method doClose
*/
doClose: function () {
this.state = P.States.closed;
this.offAll();
if (this.listener) {
this.listener.closed = true;
}
},
/**
* Called immediately before destruction.
*
* The idea is to be implemented by extenders to free additional resources on destroy.
*
* @for ProAct.Actor
* @instance
* @abstract
* @protected
* @method beforeDestroy
*/
beforeDestroy: function () {
},
/**
* Destroys this `ProAct.Actor` instance.
* <p>
* The state of <i>this</i> is set to {{#crossLink "ProAct.States/destroyed:property"}}{{/crossLink}}.
* </p>
*
* Calls {{#crossLink "ProAct.Actor/beforeDestroy:method"}}{{/crossLink}}
*
* @for ProAct.Actor
* @instance
* @method destroy
*/
destroy: function () {
if (this.state === P.States.destroyed) {
return;
}
this.beforeDestroy();
this.listeners = undefined;
if (this.listener) {
this.listener.destroyed = true;
}
this.listener = undefined;
this.errListener = undefined;
this.closeListener = undefined;
this.parent = undefined;
this.queueName = undefined;
this.transforms = undefined;
this.state = P.States.destroyed;
},
/**
* Generates the initial listeners object.
* It can be overridden for alternative listeners collections.
* It is used for resetting all the listeners too.
*
* The default types of listeners are:
* ```
* {
* change: [],
* error: [],
* close: []
* }
* ```
*
* @for ProAct.Actor
* @instance
* @protected
* @method defaultListeners
* @return {Object} A map containing the default listeners collections.
*/
defaultListeners: function () {
return {
change: [],
error: [],
close: []
};
},
/**
* A list of actions or action to be used when no action is passed for the methods working with actions.
*
* @for ProAct.Actor
* @instance
* @method defaultActions
* @protected
* @default 'change'
* @return {Array|String} The actions to be used if no actions are provided to action related methods, like
* {{#crossLink "ProAct.Actor/on:method"}}{{/crossLink}},
* {{#crossLink "ProAct.Actor/off:method"}}{{/crossLink}},
* {{#crossLink "ProAct.ActorUtil/update:method"}}{{/crossLink}}.
*/
defaultActions: function () {
return 'change';
},
/**
* Creates the <i>listener</i> of this actor.
*
* Every actor should have one listener that should pass to other actors.
*
* <p>
* This listener turns the actor in a observer.
* </p>
* <p>
* Should be overriden with specific listener, by default it returns {{#crossLink "ProAct/N:method"}}{{/crossLink}}.
* </p>
*
* @for ProAct.Actor
* @instance
* @abstract
* @method makeListener
* @protected
* @default {ProAct.N}
* @return {Object} The <i>listener of this observer</i>.
*/
makeListener: P.N,
/**
* Creates the <i>error listener</i> of this actor.
*
* Every actor should have one error listener that should pass to other actors.
*
* <p>
* This listener turns the actor in a observer for errors.
* </p>
* <p>
* Should be overriden with specific listener, by default it returns {{#crossLink "ProAct/N:method"}}{{/crossLink}}.
* </p>
*
* @for ProAct.Actor
* @instance
* @abstract
* @method makeErrListener
* @protected
* @default {ProAct.N}
* @return {Object} The <i>error listener of this observer</i>.
*/
makeErrListener: P.N,
/**
* Creates the <i>closing listener</i> of this actor.
*
* Every actor should have one closing listener that should pass to other actors.
*
* <p>
* This listener turns the actor in a observer for closing events.
* </p>
* <p>
* Should be overriden with specific listener, by default it returns {{#crossLink "ProAct/N:method"}}{{/crossLink}}.
* </p>
*
* @for ProAct.Actor
* @instance
* @abstract
* @protected
* @method makeCloseListener
* @default {ProAct.N}
* @return {Object} The <i>closing listener of this observer</i>.
*/
makeCloseListener: P.N,
/**
* Creates the <i>event</i> to be send to the listeners on update.
*
* <p>
* The <i>event</i> should be an instance of {{#crossLink "ProAct.Event"}}{{/crossLink}}.
* </p>
*
* <p>
* By default this method returns {{#crossLink "ProAct.Event.Types/value:property"}}{{/crossLink}} event.
* </p>
*
* @for ProAct.Actor
* @instance
* @method makeEvent
* @default {ProAct.Event} with type {{#crossLink "ProAct.Event.Types/value:property"}}{{/crossLink}}.
* @protected
* @param {ProAct.Event} source The source event of the event. It can be null
* @return {ProAct.Event} The event.
*/
makeEvent: function (source) {
return new P.Event(source, this, P.Event.Types.value);
},
/**
* Attaches a new listener to this `ProAct.Actor`.
*
* The listener may be function or object that defines a <i>call</i> method.
*
* ```
* actor.on(function (v) {
* console.log(v);
* });
*
* actor.on('error', function (v) {
* console.error(v);
* });
*
* actor.on({
* call: function (v) {
* console.log(v);
* }
* });
* ```
*
* @for ProAct.Actor
* @instance
* @method on
* @param {Array|String} actions
* The action/actions to listen for. If this parameter is skipped or null/undefined,
* the actions from {{#crossLink "ProAct.Actor/defaultActions:method"}}{{/crossLink}} are used.
* <p>
* The actions can be skipped and on their place as first parameter to be passed the <i>listener</i>.
* </p>
* @param {Object} listener
* The listener to attach. It must be instance of Function or object with a <i>call</i> method.
* @return {ProAct.Actor}
* <b>this</b>
*/
on: function (actions, listener) {
if (!P.U.isString(actions) && !P.U.isArray(actions)) {
listener = actions;
actions = this.defaultActions();
}
if (!P.U.isArray(actions)) {
actions = [actions];
}
var ln = actions.length,
action, i, listeners;
for (i = 0; i < ln; i ++) {
action = actions[i];
listeners = this.listeners[action];
if (!listeners) {
listeners = this.listeners[action] = [];
}
listeners.push(listener);
}
return this;
},
/**
* Removes a <i>listener</i> from the passed <i>action</i>.
*
* <p>
* If this method is called without parameters, all the listeners for all the actions are removed.
* The listeners are reset using {{#crossLink "ProAct.Actor/defaultActions:method"}}{{/crossLink}}.
* </p>
*
* Examples are:
*
* Removing a listener:
* ```
* var listener = function (v) {
* console.log(v);
* };
* actor.on(listener);
* actor.off(listener);
* ```
*
* Or for removing all the listeners attached to an actor:
* ```
* actor.off();
* ```
*
* Or for removing all the listeners of a given type attached to an actor:
* ```
* actor.off('error');
* ```
*
* Or for removing a listener from different type of actions:
* ```
* var listener = function (v) {
* console.log(v);
* };
* actor.on(listener);
* actor.onErr(listener);
*
* actor.off(['error', 'change'], listener);
* ```
*
* @for ProAct.Actor
* @instance
* @method off
* @param {Array|String} actions
* The action/actions to stop listening for. If this parameter is skipped or null/undefined,
* the actions from {{#crossLink "ProAct.Actor/defaultActions:method"}}{{/crossLink}} are used.
* <p>
* The actions can be skipped and on their place as first parameter to be passed the <i>listener</i>.
* </p>
* @param {Object} listener
* The listener to detach. If it is skipped, null or undefined all the listeners are removed from this actor.
* @return {ProAct.Actor}
* <b>this</b>
*/
off: function (actions, listener) {
if (!actions && !listener) {
this.listeners = this.defaultListeners();
return this;
}
if (!P.U.isString(actions) && !P.U.isArray(actions)) {
listener = actions;
actions = this.defaultActions();
}
if (!P.U.isArray(actions)) {
actions = [actions];
}
var ln = actions.length,
action, i, listeners;
for (i = 0; i < ln; i ++) {
action = actions[i];
listeners = this.listeners[action];
if (listeners) {
P.U.remove(listeners, listener);
}
}
return this;
},
/**
* Attaches a new error listener to this ProAct.Actor.
*
* The listener may be function or object that defines a <i>call</i> method.
*
* This is the same as calling `on('error', listener)` on an `Actor`...
*
* @for ProAct.Actor
* @instance
* @method onErr
* @param {Object} listener
* The listener to attach. It must be instance of Function or object with a <i>call</i> method.
* @return {ProAct.Actor}
* <b>this</b>
*/
onErr: function (listener) {
return this.on('error', listener);
},
/**
* Removes an error <i>listener</i> from the passed <i>action</i>.
*
* This is the same as calling `off('error', listener)` on an `Actor`...
*
* @for ProAct.Actor
* @instance
* @method offErr
* @param {Object} listener
* The listener to detach. If it is skipped, null or undefined all the listeners are removed from this actor.
* @return {ProAct.Actor}
* <b>this</b>
*/
offErr: function (listener) {
return this.off('error', listener);
},
/**
* Attaches a new close notifcation listener to this `ProAct.Actor`.
*
* The listener may be function or object that defines a <i>call</i> method.
*
* This is the same as calling `on('close', listener)` on an `Actor`...
*
* @for ProAct.Actor
* @instance
* @method onClose
* @param {Object} listener
* The listener to attach. It must be instance of Function or object with a <i>call</i> method.
* @return {ProAct.Actor}
* <b>this</b>
*/
onClose: function (listener) {
return this.on('close', listener);
},
/**
* Removes a close notification <i>listener</i> from the passed <i>action</i>.
*
* This is the same as calling `off('close', listener)` on an `Actor`...
*
* @for ProAct.Actor
* @instance
* @method offClose
* @param {Object} listener
* The listener to detach. If it is skipped, null or undefined all the listeners are removed from this actor.
* @return {ProAct.Actor}
* <b>this</b>
*/
offClose: function (listener) {
return this.off('close', listener);
},
/**
* Attaches the passed listener to listen to values, errors and the close notification from this `ProAct.Actor`.
*
* The listener may be function or object that defines a <i>call</i> method.
*
* @for ProAct.Actor
* @instance
* @method onAll
* @param {Object} listener
* The listener to attach. It must be instance of Function or object with a <i>call</i> method.
* @return {ProAct.Actor}
* <b>this</b>
*/
onAll: function (listener) {
return this.on(listener).onClose(listener).onErr(listener);
},
/**
* Removes all notifications <i>listener</i> from the passed <i>action</i>.
*
* @for ProAct.Actor
* @instance
* @method offAll
* @param {Object} listener
* The listener to detach. If it is skipped, null or undefined all the listeners are removed from this actor.
* @return {ProAct.Actor}
* <b>this</b>
*/
offAll: function (listener) {
this.off(listener);
this.off('error', listener);
return this.off('close', listener);
},
/**
* Links source actors into this actor. This means that <i>this actor</i>
* is listening for changes from the <i>sources</i>.
* <p>
* A good example is one stream to have another as as source -> if data comes into the source
* stream, it is passed to the listening too. That way the source stream is plugged <b>into</b> the listening one.
* </p>
* <p>
* The listeners from {{#crossLink "ProAct.Actor/makeListener:method"}}{{/crossLink}},
* {{#crossLink "ProAct.Actor/makeErrListener:method"}}{{/crossLink}} and {{#crossLink "ProAct.Actor/makeCloseListener:method"}}{{/crossLink}} are used.
* </p>
*
* Chaining actors is very powerful operation. It can be used to merge many source actors into one.
*
* ```
* var sourceActor1 = <Actor implementation>;
* var sourceActor2 = <Actor implementation>;
* var actor = <Actor implementation>;
*
* actor.into(sourceActor1, sourceActor2);
* actor.on(function (v) {
* console.log(v);
* });
*
* ```
*
* Now if the any of the source actors is updated, the update will be printed on the console by the `actor`.
*
* @for ProAct.Actor
* @instance
* @method into
* @param [...]
* Zero or more source ProAct.Actors to set as sources.
* @return {ProAct.Actor}
* <b>this</b>
*/
into: function () {
var args = slice.call(arguments),
ln = args.length, i, source;
for (i = 0; i < ln; i++) {
source = args[i];
source.on(this.makeListener());
source.onErr(this.makeErrListener());
source.onClose(this.makeCloseListener());
}
return this;
},
/**
* The reverse of {{#crossLink "ProAct.Actor/into:method"}}{{/crossLink}} - sets <i>this actor</i> as a source
* to the passed <i>destination</i> actor.
*
* ```
* var sourceActor = <Actor implementation>;
* var actor = <Actor implementation>;
*
* sourceActor.out(actor);
* actor.on(function (v) {
* console.log(v);
* });
*
* Now if the any of the source actors is updated, the update will be printed on the console by the `actor`.
*
* ```
*
* @for ProAct.Actor
* @instance
* @method out
* @param {ProAct.Actor} destination
* The actor to set as source <i>this</i> to.
* @return {ProAct.Actor}
* <b>this</b>
*/
out: function (destination) {
destination.into(this);
return this;
},
/**
* Adds a new <i>transformation</i> to the list of transformations
* of <i>this actor</i>.
*
* <p>
* A transformation is a function or an object that has a <i>call</i> method defined.
* This function or call method should have one argument and to return a transformed version of it.
* If the returned value is {@link ProAct.Actor.BadValue}, the next transformations are skipped and the updating
* value/event becomes - bad value.
* </p>
*
* <p>
* Every value/event that updates <i>this actor</i> will be transformed using the new transformation.
* </p>
*
* @for ProAct.Actor
* @instance
* @method transform
* @protected
* @param {Object} transformation
* The transformation to add.
* @return {ProAct.Actor}
* <b>this</b>
*/
transform: function (transformation) {
this.transforms.push(transformation);
return this;
},
/**
* Adds a new <i>transformation</i> to the list of transformations
* of <i>this actor</i>.
*
* A transformation is a function or an object that has a <i>call</i> method defined.
* This function or call method should have one argument and to return a transformed version of it.
* If the returned value is {@link ProAct.Actor.BadValue}, the next transformations are skipped and the updating
* value/event becomes - bad value.
*
* Every value/event that updates <i>this actor</i> will be transformed using the new transformation.
*
* The idea of this method is that it just calls {{#crossLink "ProAct.Actor/transform:method"}}{{/crossLink}},
* but it can be overidden from another module.
*
* TODO Maybe transformStored is a bad name
*
* @for ProAct.Actor
* @instance
* @method transformStored
* @protected
* @param {Object} transformation
* The transformation to add. Can be string - to be retrieved by name.
* @param {String} type
* The type of the transformation, for example `mapping`.
* @return {ProAct.Actor}
* <b>this</b>
*/
transformStored: function (transformation, type) {
return this.transform(transformation);
},
/**
* Adds a mapping transformation to <i>this actor</i>.
* <p>
* Mapping transformations just transform one value into another. For example if we get update with
* the value of <i>3</i> and we have mapping transformation that returns the updating value powered by <i>2</i>,
* we'll get <i>9</i> as actual updating value.
* </p>
*
* @for ProAct.Actor
* @protected
* @instance
* @method mapping
* @param {Object} mappingFunction
* Function or object with a <i>call method</i> to use as map function.
* @return {ProAct.Actor}
* <b>this</b>
*/
mapping: function (mappingFunction) {
return this.transformStored(mappingFunction, 'map');
},
/**
* Adds a filtering transformation to <i>this actor</i>.
* <p>
* Filtering can be used to filter the incoming update values. For example you can
* filter by only odd numbers as update values.
* </p>
*
* @for ProAct.Actor
* @instance
* @protected
* @method filtering
* @param {Object} filteringFunction
* The filtering function or object with a call method, should return boolean.
* @return {ProAct.Actor}
* <b>this</b>
*/
filtering: function(filteringFunction) {
var self = this,
filter = filteringFunction.call ? function (val) {
if (filteringFunction.call(self, val)) {
return val;
};
return P.Actor.BadValue;
} : filteringFunction;
return this.transformStored(filter, 'filter');
},
/**
* Adds an accumulation transformation to <i>this actor</i>.
* <p>
* Accumulation is used to compute a value based on the previous one.
* </p>
*
* @for ProAct.Actor
* @instance
* @protected
* @method accumulation
* @param {Object} initVal
* Initial value for the accumulation. For example '0' for sum.
* @param {Object} accumulationFunction
* The function to accumulate.
* @return {ProAct.Actor}
* <b>this</b>
*/
accumulation: function (initVal, accumulationFunction) {
if (!accumulationFunction) {
accumulationFunction = initVal;
initVal = undefined;
}
var self = this,
val = initVal,
acc = accumulationFunction.call ? function (newVal) {
val = accumulationFunction.call(self, val, newVal)
return val;
} : accumulationFunction;
return this.transformStored(acc, 'acc');
},
/**
* Creates a new ProAct.Actor instance with source <i>this</i> and mapping
* the passed <i>mapping function</i>.
* <p>
* Should be overridden with creating the right actor.
* </p>
*
* ```
* var actor = sourceActor.map(function (el) {
* return el * el;
* });
* ```
*
* or
*
* ```
* var actor = sourceActor.map('+');
* ```
*
* @for ProAct.Actor
* @instance
* @abstract
* @method map
* @param {Object|Function|Strin} mappingFunction
* Function or object with a <i>call method</i> to use as map function.
* Can be string for predefined mapping functions.
* @return {ProAct.Actor}
* A new ProAct.Actor instance with the <i>mapping</i> applied.
*/
map: P.N,
/**
* Creates a new ProAct.Actor instance with source <i>this</i> and filtering
* the passed <i>filtering function</i>.
* <p>
* Should be overridden with creating the right actor.
* </p>
*
* ```
* var actor = sourceActor.filter(function (el) {
* return el % 2 == 0;
* });
* ```
*
* or
*
* ```
* var actor = sourceActor.filter('odd');
*
* ```
*
* @for ProAct.Actor
* @instance
* @abstract
* @method filter
* @param {Object} filteringFunction
* The filtering function or object with a call method, should return boolean.
* @return {ProAct.Actor}
* A new ProAct.Actor instance with the <i>filtering</i> applied.
*/
filter: P.N,
/**
* Creates a new ProAct.Actor instance with source <i>this</i> and accumulation
* the passed <i>accumulation function</i>.
* <p>
* Should be overridden with creating the right actor.
* </p>
*
* ```
* var actor = sourceActor.accumulate(0, function (current, el) {
* return current + el;
* });
* ```
*
* or
*
* ```
* var actor = sourceActor.accumulate('+');
* ```
*
* @for ProAct.Actor
* @instance
* @abstract
* @method accumulate
* @param {Object} initVal
* Initial value for the accumulation. For example '0' for sum.
* @param {Object} accumulationFunction
* The function to accumulate.
* @return {ProAct.Actor}
* A new ProAct.Actor instance with the <i>accumulation</i> applied.
*/
accumulate: P.N,
/**
* Defers a ProAct.Actor listener.
* <p>
* By default this means that the listener is put into active {{#crossLink "ProAct.Flow"}}{{/crossLink}} using it's
* {{#crossLink "ProAct.Flow/pushOnce:method"}}{{/crossLink}} method, but it can be overridden.
* </p>
*
* This method determines the order of actions, triggered by the changes in the data flow.
* The default implementation is executing only one update on this Actor per data flow change.
* This means that if the `Actor` depends on other three Actors, and all of them get updated,
* it is updated only once with the last update value.
*
* @for ProAct.Actor
* @protected
* @instance
* @method defer
* @param {Object} event
* The event/value to pass to the listener.
* @param {Object} listener
* The listener to defer. It should be a function or object defining the <i>call</i> method.
* @return {ProAct.Actor}
* <i>this</i>
*/
defer: function (event, listener) {
var queueName = (listener.queueName) ? listener.queueName : this.queueName;
if (P.U.isFunction(listener)) {
P.flow.pushOnce(queueName, listener, [event]);
} else {
P.flow.pushOnce(queueName, listener, listener.call, [event]);
}
return this;
}
};