Skip to content
Snippets Groups Projects
Commit e611d3c3 authored by Andreas Tolfsen's avatar Andreas Tolfsen
Browse files

Bug 1381876 - Introduce TimedPromise. r=automatedtester

This introduces a specialisation of the well-known Promise that can
time out after a set limit, causing the promises' "reject" callback to
be invoked.

The TimedPromise object represents the timed, eventual completion
(or failure) of an asynchronous operation, and its resulting value.
In contrast to a regular Promise, it times out after a set timeframe.

MozReview-Commit-ID: Rb3POsPYeT

--HG--
extra : rebase_source : cdff792dfa43af3cff1b20b3e81edb1a826e561e
parent c956360d
No related branches found
No related tags found
No related merge requests found
...@@ -6,9 +6,12 @@ ...@@ -6,9 +6,12 @@
const {classes: Cc, interfaces: Ci, utils: Cu} = Components; const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("chrome://marionette/content/error.js"); const {
error,
TimeoutError,
} = Cu.import("chrome://marionette/content/error.js", {});
this.EXPORTED_SYMBOLS = ["wait"]; this.EXPORTED_SYMBOLS = ["wait", "TimedPromise"];
/** /**
* Poll-waiting utilities. * Poll-waiting utilities.
...@@ -17,6 +20,8 @@ this.EXPORTED_SYMBOLS = ["wait"]; ...@@ -17,6 +20,8 @@ this.EXPORTED_SYMBOLS = ["wait"];
*/ */
this.wait = {}; this.wait = {};
const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
/** /**
* @callback Condition * @callback Condition
* *
...@@ -104,9 +109,8 @@ wait.until = function(func, timeout = 2000, interval = 10) { ...@@ -104,9 +109,8 @@ wait.until = function(func, timeout = 2000, interval = 10) {
// before invoking |evalFn| // before invoking |evalFn|
evalFn(); evalFn();
timer.init(evalFn, interval, Ci.nsITimer.TYPE_REPEATING_SLACK); timer.init(evalFn, interval, TYPE_REPEATING_SLACK);
// cancel timer and propagate result
}).then(res => { }).then(res => {
timer.cancel(); timer.cancel();
return res; return res;
...@@ -115,3 +119,59 @@ wait.until = function(func, timeout = 2000, interval = 10) { ...@@ -115,3 +119,59 @@ wait.until = function(func, timeout = 2000, interval = 10) {
throw err; throw err;
}); });
}; };
/**
* The <code>TimedPromise</code> object represents the timed, eventual
* completion (or failure) of an asynchronous operation, and its
* resulting value.
*
* In contrast to a regular {@link Promise}, it times out after
* <var>timeout</var>.
*
* @param {Condition} func
* Function to run, which will have its <code>reject</code>
* callback invoked after the <var>timeout</var> duration is reached.
* It is given two callbacks: <code>resolve(value)</code> and
* <code>reject(error)</code>.
* @param {timeout=} [timeout=1500] timeout
* <var>condition</var>'s <code>reject</code> callback will be called
* after this timeout.
* @param {Error=} [throws=TimeoutError] throws
* When the <var>timeout</var> is hit, this error class will be
* thrown. If it is null, no error is thrown and the promise is
* instead resolved on timeout.
*
* @return {Promise.<*>}
* Timed promise.
*/
function TimedPromise(fn, {timeout = 1500, throws = TimeoutError} = {}) {
const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
return new Promise((resolve, reject) => {
// Reject only if |throws| is given. Otherwise it is assumed that
// the user is OK with the promise timing out.
let bail = res => {
if (throws !== null) {
let err = new throws();
reject(err);
} else {
resolve();
}
};
timer.initWithCallback({notify: bail}, timeout, TYPE_ONE_SHOT);
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}).then(res => {
timer.cancel();
return res;
}, err => {
timer.cancel();
throw err;
});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment