mw.loader: Use requestIdleCallback to update module store

.. instead of setTimeout.

Also adapt the code accordingly since it is no longer needed to
cancel and re-schedule an update every time update() is called.
This is already handled by requestIdleCallback.

We can let the already-scheduled callback survive. The data
that will be saved is serialised during the flush anyway,
not when scheduling.

Change-Id: Iea48919b4baba7647040b6ed9ff4b6d0d387b962
This commit is contained in:
Timo Tijhof 2015-11-10 22:09:21 +00:00
parent 866f3831e3
commit 4174b662f6

View file

@ -2277,15 +2277,13 @@
}, },
/** /**
* Sync modules to localStorage. * Sync in-memory store back to localStorage.
* *
* This function debounces localStorage updates. When called multiple times in * This function debounces updates. When called with a flush already pending,
* quick succession, the calls are coalesced into a single update operation. * the call is coalesced into the pending update. The call to
* This allows us to call #update without having to consider the module load * localStorage.setItem will be naturally deferred until the page is quiescent.
* queue; the call to localStorage.setItem will be naturally deferred until the
* page is quiescent.
* *
* Because localStorage is shared by all pages with the same origin, if multiple * Because localStorage is shared by all pages from the same origin, if multiple
* pages are loaded with different module sets, the possibility exists that * pages are loaded with different module sets, the possibility exists that
* modules saved by one page will be clobbered by another. But the impact would * modules saved by one page will be clobbered by another. But the impact would
* be minor and the problem would be corrected by subsequent page views. * be minor and the problem would be corrected by subsequent page views.
@ -2293,16 +2291,16 @@
* @method * @method
*/ */
update: ( function () { update: ( function () {
var timer; var hasPendingWrite = false;
function flush() { function flushWrites() {
var data, var data, key;
key = mw.loader.store.getStoreKey(); if ( !hasPendingWrite || !mw.loader.store.enabled ) {
return;
if ( !mw.loader.store.enabled ) {
return false;
} }
mw.loader.store.prune(); mw.loader.store.prune();
key = mw.loader.store.getStoreKey();
try { try {
// Replacing the content of the module store might fail if the new // Replacing the content of the module store might fail if the new
// contents would exceed the browser's localStorage size limit. To // contents would exceed the browser's localStorage size limit. To
@ -2314,11 +2312,15 @@
} catch ( e ) { } catch ( e ) {
mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-update' } ); mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-update' } );
} }
hasPendingWrite = false;
} }
return function () { return function () {
clearTimeout( timer ); if ( !hasPendingWrite ) {
timer = setTimeout( flush, 2000 ); hasPendingWrite = true;
mw.requestIdleCallback( flushWrites );
}
}; };
}() ) }() )
} }