Search code examples
javascriptajaxxmlhttprequest

Set a duration for xhr.onload to be delayed


Currently I'm playing around with asynchronous page loading and I have reached the following implementation for when response is received:

xhr.onload = function( event ) {
    var res = event.target.responseXML;

    // Update page content
    setTimeout( function() {
        content.innerHTML = res.querySelector( '.content' ).innerHTML;
    }, 250 );
};

I've set a delay of 250 ms to make sure that the previous content block has a chance to finish its fade out animation before replacing and fading in the new content. The problem with this is that there will always be a delay when content is loaded unless I get the xhr response instantly (which of course won't happen in the real world).

What would be the best way to wait at least 250ms before allowing the page to render the new content — that is:

  • If it takes 100ms to get a xhr response, still need to wait 150ms before replacing the content
  • If it takes 1 second to get xhr response, the old content block fade out has long since finished therefore load the new content immediately.

Solution

  • Update

    I now have a solution that works however it doesn't seem very elegant.

    function fetchPage() {
        var xhr = new XMLHttpRequest();
        var hasFinishedAnimating = false;
        var res;
    
        xhr.open( 'GET', window.location.href, true );
        xhr.responseType = 'document';
        xhr.send();
    
        // [1]
        setTimeout( function() {
            hasFinishedAnimating = true;
            if ( res ) updateContent( res );
        }, 250 );
    
        // [2]
        xhr.onload = function( event ) {
            res = event.target.responseXML.querySelector( '.content' ).innerHTML;
            if ( hasFinishedAnimating ) updateContent( res );
        };
    }
    
    // Update page content
    function updateContent( html ) {
        content.innerHTML = html;
    }
    

    So what is happening here is that there is a race going on. One of the following cases will complete first:

    • [1] the countdown (fade out animation) will finish
    • [2] the new content is fetched

    The case that runs first will always fail — [1] as content is still being fetched and [2] because the animation has not finished.

    It is only when the losing case runs the content will finally be updated.