jonathantneal / document-promises

Document loading states as Promises
Creative Commons Zero v1.0 Universal
53 stars 7 forks source link

Different browser behavior for code execution on "complete" readystate and load event firing #14

Open aaarichter opened 5 years ago

aaarichter commented 5 years ago

Hi,

we used document-promises loaded in our project to substitute $(window).on('load, ... ). Shortly after releasing it to production we noticed weird browser dependent issues like increases in latency, as well as missing performance metrics. The performance metrics is captured and send on window load event via window.addEventListener('load', ... ).

Reading the readystate documentation carefully gave us the first clue that complete indicates that the load event is about to fire.

Executing lots of code on this event caused Safari to overstep the load event, thus failing to execute code. Chrome, on the other hand, was still firing the load event but was pushed it later point in time due to code execution on the complete readystate event.

We removed document-promises and implemented a similar solution which executes the callback after window load.

'use strict';

/**
 *
 * @param {Window|Document} context
 * @param {string} event
 * @param {function} test
 * @return {Promise<any>}
 */
function thenify(context, event, test) {
  return new Promise(
    resolve =>
      test()
        ? resolve()
        : context.addEventListener(event, resolve, { once: true })
  );
}

/**
 *
 * @type {Promise<any>}
 */
exports.windowLoaded = thenify(
  window,
  'load',
  () => document.readyState === 'complete'
);

/**
 *
 * @type {Promise<any>}
 */
exports.documentReady = thenify(
  document,
  'DOMContentLoaded',
  () => document.readyState !== 'loading'
);
jonathantneal commented 5 years ago

Thanks so much for sharing this. What an interesting find. I’ve asked how the real implementation should handle this. If there’s a problem with my implementation, or it’s just safer to leverage the window's load event, then I’ll make that change and release a new major version.