define( | |
['Q', 'jquery'], | |
function(Q, $) { | |
'use strict'; | |
function withPromises() { | |
/*jshint validthis: true */ | |
/** | |
* Dispatch a message, receiving a promise for the response. | |
* Possible attributes on args: | |
* type - event type used to communicate with handler (required) | |
* element - where to dispatch the event (defaults to component node) | |
* responseType - event type produced by handler with response (defaults to type + 'Response') | |
* errorType - event type produced by handler when call fails (defaults to type + 'Error') | |
* timeout - ms to wait for response before an error is generated. If set to 0, no timeout is used. (defaults to 0, no timeout) | |
* | |
* @param args option containing all arguments. The only required argument is type. | |
* | |
* @returns a promise | |
*/ | |
this.call = function(args) { | |
var deferred = Q.defer(), | |
correlator = {}, | |
timer; | |
// add defaults | |
args = $.extend({ | |
element: this.node, | |
responseType: args.type + 'Response', | |
errorType: args.type + 'Error', | |
timeout: 0 | |
}, args); | |
this.on(args.element, args.responseType, function(ev, data) { | |
if (data.correlator === correlator) { | |
if (timer) { | |
clearTimeout(timer); | |
} | |
deferred.resolve(data.data); | |
} | |
}); | |
this.on(args.element, args.errorType, function(ev, data) { | |
if (data.correlator === correlator) { | |
if (timer) { | |
clearTimeout(timer); | |
} | |
deferred.reject(new Error(data.data)); | |
} | |
}); | |
if (args.timeout > 0) { | |
timer = setTimeout(function() { | |
deferred.reject('Call timed out'); | |
}, args.timeout); | |
} | |
this.trigger(args.element, args.type, { | |
correlator: correlator, | |
data: args.data | |
}); | |
return deferred.promise; | |
}; | |
/** | |
* Register a callback for a message generated via the dispatch method. | |
* | |
* @param args option containing all arguments. The two required arguments are type and callback | |
*/ | |
this.registerCall = function(args) { | |
var component = this, response; | |
args = $.extend({ | |
element: this.node, | |
responseType: args.type + 'Response', | |
errorType: args.type + 'Error' | |
}, args); | |
args.callback = args.callback.bind(this); | |
this.on(args.element, args.type, function(ev, data) { | |
var correlator = data.correlator, origData = data.data; | |
try { | |
response = args.callback(origData); | |
component.trigger(args.element, args.responseType, | |
{ correlator: correlator, data: response }); | |
} catch (err) { | |
component.trigger(args.element, args.errorType, | |
{ correlator: correlator, data: err }); | |
} | |
}); | |
}; | |
} | |
// return the mixin function | |
return withPromises; | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment