1 // Copyright (c) 2014 Kris Maglione <maglione.k at Gmail>
3 // This work is licensed for reuse under an MIT license. Details are
4 // given in the LICENSE.txt file included with this file.
7 defineModule("promises", {
8 exports: ["Promise", "Task", "promises"],
12 lazyRequire("services", ["services"]);
14 lazyRequire("resource://gre/modules/Promise.jsm", ["Promise"]);
15 lazyRequire("resource://gre/modules/Task.jsm", ["Task"]);
17 function withCallbacks(fn) {
18 return function wrapper(...args) {
19 let deferred = Promise.defer();
20 function resolve(arg) { deferred.resolve(arg); }
21 function reject(arg) { deferred.reject(arg); }
22 fn.apply(this, [[resolve, reject, deferred]].concat(args));
23 return deferred.promise;
27 var Promises = Module("Promises", {
31 * Allows promises to be canceled..
33 * @param {Promise} promise The promise to cancel.
34 * @param {*} arg Argument to be passed to the cancellation
37 cancel: function cancel(promise, reason) {
38 let cleanup = this._cancel.get(promise);
41 cleanup[1].reject(reason);
43 this._cancel.delete(promise);
47 * Registers a cleanup function for the given deferred promise.
49 * @param {Deferred} promise The promise to cancel.
50 * @param {function} fn The cleanup function.
52 oncancel: function oncancel(deferred, fn) {
53 this._cancel.set(deferred.promise, [fn, deferred]);
57 * Returns a promise which resolves after a brief delay.
59 delay: withCallbacks(function delay([accept]) {
60 let { mainThread } = services.threading;
61 mainThread.dispatch(accept, mainThread.DISPATCH_NORMAL);
65 * Returns a promise which resolves with the given argument.
67 accept: function fail(arg) {
68 let deferred = Promise.defer();
69 deferred.resolve(arg);
70 return deferred.promise;
74 * Returns a promise which fails with the given argument.
76 fail: function fail(arg) {
77 let deferred = Promise.defer();
79 return deferred.promise;
83 * Returns a promise which resolves after the given number of
86 * @param {number} delay The number of milliseconds to wait.
88 sleep: withCallbacks(function sleep([callback], delay) {
89 this.timeout(callback, delay);
93 * Wraps the given function so that each call spawns a Task.
95 * @param {function} fn The function to wrap.
98 task: function task(fn) {
99 return function task_(...args) {
100 return Task.spawn(fn.bind.apply(fn, [this].concat(args)));
105 * Returns a promise which resolves when the function *test* returns
106 * true, or *timeout* milliseconds have expired.
108 * @param {function} test The predicate on which to wait.
109 * @param {Number} timeout The maximum number of milliseconds to
112 * @param {number} pollInterval The poll interval, in milliseconds.
115 waitFor: withCallbacks(function waitFor([accept, reject], test, timeout=null, pollInterval=10) {
116 let end = timeout && Date.now() + timeout, result;
118 let timer = services.Timer(
132 pollInterval, services.Timer.TYPE_REPEATING_SLACK);
136 * Wraps the given function so that its first argument is an array
137 * of success and failure callbacks which, when called, resolve the
140 * @param {function} fn The function to wrap.
143 withCallbacks: withCallbacks,
148 // vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript: