'use strict';
/**
* @classdesc This class enables pending callbacks to fire all at once, on a
* synchronized schedule instead of one by one. This is useful to group
* operations that wake up expensive resources such as a mobile radio.
*
* @example
* enqueue = ( new BackgroundQueue() ).add;
* ...
* enqueue( callback );
* // callbacks will be fired in batches every 30 seconds (default)
*
* @class mw.eventLog.BackgroundQueue
* @param {number} [intervalSecs=30] seconds to wait before calling callbacks
*/
module.exports = function BackgroundQueue( intervalSecs ) {
let timer = null;
const pendingCallbacks = [];
let discardingPage;
const queue = this;
intervalSecs = intervalSecs || 30;
/**
* Add a callback to the queue, to be flushed when the timer runs out.
*
* @method flush
* @param {Function} fn Callback to add
* @memberof mw.eventLog.BackgroundQueue
* @instance
*/
queue.add = function ( fn ) {
if ( discardingPage ) {
// If we're in the middle of discarding this page, every add will
// immediately run the callback to avoid losing data.
fn();
return;
}
pendingCallbacks.push( fn );
if ( !timer ) {
timer = setTimeout( queue.flush, intervalSecs * 1000 );
}
};
/**
* Manually execute all the callbacks, same as if the timer runs out.
*
* @method flush
* @memberof mw.eventLog.BackgroundQueue
* @instance
*/
queue.flush = function () {
if ( timer ) {
clearTimeout( timer );
timer = null;
}
while ( pendingCallbacks.length ) {
pendingCallbacks.shift()();
}
};
// If the user navigates to another page or closes the tab/window/application,
// then send any queued events.
// Listen to the pagehide and visibilitychange events as Safari 12 and Mobile Safari 11
// don't appear to support the Page Visbility API yet.
window.addEventListener( 'pagehide', () => {
// Record when the page is in the process of being discarded.
discardingPage = true;
queue.flush();
} );
// If the page was just suspended and gets reactivated, re-enable queuing.
window.addEventListener( 'pageshow', () => {
discardingPage = false;
} );
// https://developer.mozilla.org/en-US/docs/Web/API/Document/onvisibilitychange
document.addEventListener( 'visibilitychange', () => {
if ( document.hidden ) {
queue.flush();
}
} );
// Not allowed outside unit tests
if ( window.QUnit ) {
queue.getTimer = function () {
return timer;
};
queue.getCallbacks = function () {
return pendingCallbacks;
};
}
};