4831: Add more error checking to mithril deferred.onerror.
[arvados.git] / apps / backstage / app / util.js
1 module.exports = {
2     choose: choose,
3     debounce: debounce,
4 };
5
6 // util.choose('a', {a: 'A', b: 'B'}) --> return 'A'
7 // util.choose('a', {a: [console.log, 'foo']}) --> return console.log('foo')
8 function choose(key, options) {
9     var option = options[key];
10     if (option instanceof Array && option[0] instanceof Function)
11         return option[0].apply(this, option.slice(1));
12     else
13         return option;
14 }
15
16 // util.debounce(250, key) --> Return a promise. If someone else
17 // calls debounce with the same key, reject the promise. If nobody
18 // else has done so after 250ms, resolve the promise.
19 function debounce(ms, key) {
20     var newpending;
21     util.debounce.pending = util.debounce.pending || [];
22     util.debounce.pending.map(function(found) {
23         if (!newpending && found.key === key) {
24             // Promise already pending with this key. Reject the old
25             // one, reuse its slot for the new one.
26             window.clearTimeout(found.timer);
27             found.deferred.reject();
28             m.endComputation();
29             newpending = found;
30         }
31     });
32     if (!newpending) {
33         // No pending promise with this key.
34         newpending = {key: key}
35         util.debounce.pending.push(newpending);
36     }
37     newpending.deferred = m.deferred();
38     m.startComputation();
39     newpending.timer = window.setTimeout(function() {
40         // Success, no more bouncing. Remove from pending list.
41         util.debounce.pending.map(function(found, i) {
42             if (found === newpending) {
43                 util.debounce.pending.splice(i, 1);
44                 found.deferred.resolve();
45                 m.endComputation();
46             }
47         });
48     }, ms);
49     return newpending.deferred.promise;
50 }
51
52 // Override mithril's default deferred.onerror, with more error checking
53 var m = require('mithril');
54 m.deferred.onerror = function(e) {
55     if ({}.toString.call(e) === "[object Error]" &&
56         !(e.constructor &&
57           e.constructor.toString() &&
58           e.constructor.toString().match(/ Error/)))
59         throw e;
60 };