luci-base: luci.js: introduce generic LuCI.Poll
Introduce a new LuCI.Poll class which is able to repeat any promise based function and not strictly tied to HTTP request semantics. Also rework LuCI.Request.Poll and XHR.Poll as well as LuCI.start(), LuCI.stop(), LuCI.halt() etc. to redirect to the new api. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
8a8e8e0aac
commit
eee323cb66
1 changed files with 110 additions and 78 deletions
|
@ -331,49 +331,94 @@
|
||||||
return (this.interceptors.length < oldlen);
|
return (this.interceptors.length < oldlen);
|
||||||
},
|
},
|
||||||
|
|
||||||
poll: Class.singleton({
|
poll: {
|
||||||
__name__: 'LuCI.Request.Poll',
|
|
||||||
|
|
||||||
queue: [],
|
|
||||||
|
|
||||||
add: function(interval, url, options, callback) {
|
add: function(interval, url, options, callback) {
|
||||||
if (isNaN(interval) || interval <= 0)
|
if (isNaN(interval) || interval <= 0)
|
||||||
throw new TypeError('Invalid poll interval');
|
throw new TypeError('Invalid poll interval');
|
||||||
|
|
||||||
|
var ival = interval >>> 0,
|
||||||
|
opts = Object.assign({}, options, { timeout: ival * 1000 - 5 });
|
||||||
|
|
||||||
|
return Poll.add(function() {
|
||||||
|
return Request.request(url, options).then(function(res) {
|
||||||
|
if (!Poll.active())
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
callback(res, res.json(), res.duration);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
callback(res, null, res.duration);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, ival);
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function(entry) { return Poll.remove(entry) },
|
||||||
|
start: function() { return Poll.start() },
|
||||||
|
stop: function() { return Poll.stop() },
|
||||||
|
active: function() { return Poll.active() }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Poll = Class.singleton({
|
||||||
|
__name__: 'LuCI.Poll',
|
||||||
|
|
||||||
|
queue: [],
|
||||||
|
|
||||||
|
add: function(fn, interval) {
|
||||||
|
if (interval == null || interval <= 0)
|
||||||
|
interval = window.L ? window.L.env.pollinterval : null;
|
||||||
|
|
||||||
|
if (isNaN(interval) || typeof(fn) != 'function')
|
||||||
|
throw new TypeError('Invalid argument to LuCI.Poll.add()');
|
||||||
|
|
||||||
|
for (var i = 0; i < this.queue.length; i++)
|
||||||
|
if (this.queue[i].fn === fn)
|
||||||
|
return false;
|
||||||
|
|
||||||
var e = {
|
var e = {
|
||||||
interval: interval,
|
r: true,
|
||||||
url: url,
|
i: interval >>> 0,
|
||||||
options: options,
|
fn: fn
|
||||||
callback: callback
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.queue.push(e);
|
this.queue.push(e);
|
||||||
return e;
|
|
||||||
|
if (this.tick != null && !this.active())
|
||||||
|
this.start();
|
||||||
|
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
remove: function(entry) {
|
remove: function(entry) {
|
||||||
var oldlen = this.queue.length, i = oldlen;
|
if (typeof(fn) != 'function')
|
||||||
|
throw new TypeError('Invalid argument to LuCI.Poll.remove()');
|
||||||
|
|
||||||
while (i--)
|
var len = this.queue.length;
|
||||||
if (this.queue[i] === entry) {
|
|
||||||
delete this.queue[i].running;
|
|
||||||
this.queue.splice(i, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.queue.length)
|
for (var i = len; i > 0; i--)
|
||||||
this.stop();
|
if (this.queue[i-1].fn === fn)
|
||||||
|
this.queue.splice(i-1, 1);
|
||||||
|
|
||||||
return (this.queue.length < oldlen);
|
if (!this.queue.length && this.stop())
|
||||||
|
this.tick = 0;
|
||||||
|
|
||||||
|
return (this.queue.length != len);
|
||||||
},
|
},
|
||||||
|
|
||||||
start: function() {
|
start: function() {
|
||||||
if (!this.queue.length || this.active())
|
if (this.active())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this.tick = 0;
|
this.tick = 0;
|
||||||
|
|
||||||
|
if (this.queue.length) {
|
||||||
this.timer = window.setInterval(this.step, 1000);
|
this.timer = window.setInterval(this.step, 1000);
|
||||||
this.step();
|
this.step();
|
||||||
document.dispatchEvent(new CustomEvent('poll-start'));
|
document.dispatchEvent(new CustomEvent('poll-start'));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -389,39 +434,24 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
step: function() {
|
step: function() {
|
||||||
Request.poll.queue.forEach(function(e) {
|
for (var i = 0, e = null; (e = Poll.queue[i]) != null; i++) {
|
||||||
if ((Request.poll.tick % e.interval) != 0)
|
if ((Poll.tick % e.i) != 0)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
if (e.running)
|
if (!e.r)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
var opts = Object.assign({}, e.options,
|
e.r = false;
|
||||||
{ timeout: e.interval * 1000 - 5 });
|
|
||||||
|
|
||||||
e.running = true;
|
Promise.resolve(e.fn()).finally((function() { this.r = true }).bind(e));
|
||||||
Request.request(e.url, opts)
|
|
||||||
.then(function(res) {
|
|
||||||
if (!e.running || !Request.poll.active())
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
e.callback(res, res.json(), res.duration);
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
|
||||||
e.callback(res, null, res.duration);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(function() { delete e.running });
|
|
||||||
});
|
|
||||||
|
|
||||||
Request.poll.tick = (Request.poll.tick + 1) % Math.pow(2, 32);
|
Poll.tick = (Poll.tick + 1) % Math.pow(2, 32);
|
||||||
},
|
},
|
||||||
|
|
||||||
active: function() {
|
active: function() {
|
||||||
return (this.timer != null);
|
return (this.timer != null);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -635,7 +665,7 @@
|
||||||
if (res.status != 403 || res.headers.get('X-LuCI-Login-Required') != 'yes')
|
if (res.status != 403 || res.headers.get('X-LuCI-Login-Required') != 'yes')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Request.poll.stop();
|
Poll.stop();
|
||||||
|
|
||||||
L.ui.showModal(_('Session expired'), [
|
L.ui.showModal(_('Session expired'), [
|
||||||
E('div', { class: 'alert-message warning' },
|
E('div', { class: 'alert-message warning' },
|
||||||
|
@ -654,7 +684,8 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
originalCBIInit();
|
originalCBIInit();
|
||||||
Request.poll.start();
|
|
||||||
|
Poll.start();
|
||||||
|
|
||||||
document.dispatchEvent(new CustomEvent('luci-loaded'));
|
document.dispatchEvent(new CustomEvent('luci-loaded'));
|
||||||
},
|
},
|
||||||
|
@ -722,9 +753,9 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
stop: function(entry) { return Request.poll.remove(entry) },
|
stop: function(entry) { return Poll.remove(entry) },
|
||||||
halt: function() { return Request.poll.stop() },
|
halt: function() { return Poll.stop() },
|
||||||
run: function() { return Request.poll.start() },
|
run: function() { return Poll.start() },
|
||||||
|
|
||||||
/* DOM manipulation */
|
/* DOM manipulation */
|
||||||
dom: Class.singleton({
|
dom: Class.singleton({
|
||||||
|
@ -965,6 +996,7 @@
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
Poll: Poll,
|
||||||
Class: Class,
|
Class: Class,
|
||||||
Request: Request,
|
Request: Request,
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue