ares-ide
Version:
A browser-based code editor and UI designer for Enyo 2 projects
167 lines (162 loc) • 4.88 kB
JavaScript
/**
_enyo.Async_ is the base kind for handling asynchronous operations.
_enyo.Async_ is an **Object**, not a **Component**; thus, you may not declare
an _Async_ in a _components_ block. If you want to use _Async_ as a
component, you should probably be using
<a href="#enyo.WebService">enyo.WebService</a> instead.
An Async object represents a task that has not yet completed. You may attach
callback functions to an Async, to be called when the task completes or
encounters an error.
More information on _Async_ and its usage is available in the documentation on
[Consuming Web Services](building-apps/managing-data/consuming-web-services.html)
in the Enyo Developer Guide.
*/
enyo.kind({
name: "enyo.Async",
kind: "enyo.Object",
published: {
/**
If set to a non-zero value, the number of milliseconds to
wait after the _go_ call before failing with the "timeout" error
*/
timeout: 0
},
//* @protected
failed: false,
context: null,
constructor: enyo.inherit(function (sup) {
return function() {
sup.apply(this, arguments);
this.responders = [];
this.errorHandlers = [];
this.progressHandlers = [];
};
}),
destroy: enyo.inherit(function (sup) {
return function() {
if (this.timeoutJob) {
this.clearTimeout();
}
sup.apply(this, arguments);
};
}),
accumulate: function(inArray, inMethodArgs) {
var fn = (inMethodArgs.length < 2) ? inMethodArgs[0] : enyo.bind(inMethodArgs[0], inMethodArgs[1]);
inArray.push(fn);
},
//* @public
/**
Registers a response function.
First parameter is an optional _this_ context for the response method.
Second (or only) parameter is the function object.
*/
response: function(/* [inContext], inResponder */) {
this.accumulate(this.responders, arguments);
return this;
},
/**
Registers an error handler.
First parameter is an optional _this_ context for the response method.
Second (or only) parameter is the function object.
*/
error: function(/* [inContext], inResponder */) {
this.accumulate(this.errorHandlers, arguments);
return this;
},
//* @protected
route: function(inAsync, inValue) {
var r = this.bindSafely("respond");
inAsync.response(function(inSender, inValue) {
r(inValue);
});
var f = this.bindSafely("fail");
inAsync.error(function(inSender, inValue) {
f(inValue);
});
inAsync.go(inValue);
},
handle: function(inValue, inHandlers) {
var r = inHandlers.shift();
if (r) {
if (r instanceof enyo.Async) {
this.route(r, inValue);
} else {
// handler can return a new 'value'
var v = enyo.call(this.context || this, r, [this, inValue]);
// ... but only if it returns something other than undefined
v = (v !== undefined) ? v : inValue;
// next handler
(this.failed ? this.fail : this.respond).call(this, v);
}
}
},
startTimer: function() {
this.startTime = enyo.now();
if (this.timeout) {
this.timeoutJob = setTimeout(this.bindSafely("timeoutComplete"), this.timeout);
}
},
endTimer: function() {
if (this.timeoutJob) {
this.endTime = enyo.now();
clearTimeout(this.timeoutJob);
this.timeoutJob = null;
this.latency = this.endTime - this.startTime;
}
},
timeoutComplete: function() {
this.timedout = true;
this.fail("timeout");
},
//* @protected
//* Called as part of the async implementation; triggers the handler chain.
respond: function(inValue) {
this.failed = false;
this.endTimer();
this.handle(inValue, this.responders);
},
//* @public
//* Can be called from any handler to trigger the error chain.
fail: function(inError) {
this.failed = true;
this.endTimer();
this.handle(inError, this.errorHandlers);
},
//* Called from an error handler; clears the error condition and resumes
//* calling handler methods.
recover: function() {
this.failed = false;
},
//* @public
/**
Registers a progress handler.
First parameter is an optional _this_ context for the response method.
Second (or only) parameter is the function object.
Progress handlers are called with the sender as the first argument and a progress event as the second argument.
*/
progress: function(/* [inContext], inResponder */) {
this.accumulate(this.progressHandlers, arguments);
return this;
},
//* @protected
//* Notifies the progress handlers
sendProgress: function(current, min, max, sourceEvent) {
var event = enyo.mixin({}, sourceEvent);
event.type = 'progress';
event.current = current;
event.min = min;
event.max = max;
for (var i = 0; i < this.progressHandlers.length; i++) {
enyo.call(this.context || this, this.progressHandlers[i], [this, event]);
}
},
//* Starts the async activity. Overridden in subkinds.
go: function(inValue) {
this.sendProgress(0, 0, 1);
enyo.asyncMethod(this, function() {
this.sendProgress(1, 0, 1);
this.respond(inValue);
});
return this;
}
});