3

I'm working with Navigation timing object to calculate full page delay between navigation start and load event end.

My goal is to get performance.timing.loadEventEnd - performance.timing.navigationStart; when load event is done.

However, invoking this code inside load event, load event end can not be measured. So, I need to defer it and run outside of load event.

Here are my requirements

  1. calling myfunction after load event ends.
  2. I don't want to use timing function like setTimeout. If setTimeout guarantee that it does not wake up during other load event, it is ok to use.
  3. I don't want to calculate time delay inside load event. (like call new Date().getTime() or performance.now() at the top of load event, and call it again before finish and subtract it.) Because I use bunch of 3rd party library which also call load event. I can't handle all of them.
  4. should work cross browser environment, IE>=10
$(window).ready(function(){
    console.log("domContentLoadedEventStart: "
        +performance.timing.domContentLoadedEventStart);
    console.log("domContentLoadedEventEnd: "
        +performance.timing.domContentLoadedEventEnd);
});
// result:
// > domContentLoadedEventStart: 1451979544555
// > domContentLoadedEventEnd: 0

$(window).load(function(){
    console.log("domcomplete: "+performance.timing.domComplete);
    console.log("loadEventStart: "+performance.timing.loadEventStart);
    console.log("loadEventEnd: "+performance.timing.loadEventEnd);
});
// result:
// > domcomplete: 1451979906417
// > loadEventStart: 1451979906417
// > loadEventEnd: 0

EDIT

I've tested this suites. This test cases were intended to wake up setTimeout during load function callback.

// myfunction which will be called by setTimeout in firstLoadCallback.
function myfunction(){
    console.log("called myfunction");
}

// first load callback
$(window).load(function firstLoadCallback(){
    var startTicks = performance.now();

    // register myfunction with setTimeout
    setTimeout(myfunction, 0);

    // sleep +500ms
    while(performance.now() - startTicks < 500){
        ;
    }

    var diffTicks = performance.now() - startTicks;

    console.log("first ticks: "+diffTicks);
});

// second load callback
$(window).load(function secondLoadCallback(){
    var startTicks = performance.now();

    // sleep +500ms
    while(performance.now() - startTicks < 500){
        ;
    }

    var diffTicks = performance.now() - startTicks;

    console.log("second ticks: "+diffTicks);
});

// third callback from other file: other-file.js
$(window).load(function thirdLoadCallback(){
    var startTicks = performance.now();

    // sleep +500ms
    while(performance.now() - startTicks < 500){
        ;
    }

    var diffTicks = performance.now() - startTicks;

    console.log("third ticks: "+diffTicks);
});

// result:
// first ticks: 500.005
// second ticks: 500.0050000000001
// third ticks: 500.0049999999999
// called myfunction

From this result, callback which registered by setTimeout does not wake up before function call tree end. If this result guarantee of working cross browser, @BenjaminGruenbaum answer might be correct.

I will post another question about it.

Lukabot
  • 189
  • 3
  • 11
  • You have to schedule a task to run after the load event has completed. There are no hooks for this - you'd have to use a `setTimeout(fn, 0)` or something similar. – Benjamin Gruenbaum Jan 05 '16 at 07:57
  • @BenjaminGruenbaum What if other load callback function called after ```myfunction```? Does setTimeout guarantee of it? – Lukabot Jan 05 '16 at 07:59
  • `setTimeout` will register an event to execute in next tick. So yes. But as you have already mentioned you do not want to use setTimeout, you can look into `promise` – Rajesh Jan 05 '16 at 08:05
  • @Lukabot the `setTimeout` has to be inside of the `$(window).load` event. – Benjamin Gruenbaum Jan 05 '16 at 08:09
  • @Rajesh I mean, if I registered ```setTimeout``` in my first load callback. After that, my second load callback starts running. What if second function takes too much time? Does ```setTimeout``` wakes up while second function is running? @BenjaminGruenbaum Yes, I put it in the right position. – Lukabot Jan 05 '16 at 08:31
  • No. For such cases, you should use `Promise`. A quick workaround can be passing a callback function to second callback, and call function there directly, without `setTimeout`. But this can get little complicated and you should look into [Callback Hell](http://stackoverflow.com/questions/25098066/what-is-callback-hell-and-how-and-why-rx-solves-it) – Rajesh Jan 05 '16 at 08:34

1 Answers1

2

You don't really have a choice except of nesting the load event and a setTimeout.

$(window).load(function(){ 
    setTimeout(function() { 
        // your above code goes here
    }, 0); // 0, since we just want it to defer.
});

// or without jQuery:
window.addEventListener("load", function() { // IE9+
    setTimeout(function() { 
        // your above code goes here
    }, 0); // 0, since we just want it to defer.
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504