user1653251
user1653251

Reputation: 11

Delay code execution until download is finished

I'm writing a script that will dynamically update forum pages for me. Not only is this convenient, but I figure it's a good exercise to get more acquainted with Javascript and DOM.

To get an updated list of posts, I have to fetch the latest version of the page. I'm doing that with XmlHttpRequest:

function getNewDOM(url) {
    console.log("getNewDOM()");
    // Get the page
    var request = new XMLHttpRequest();
    request.open("GET", url, false);
    request.send(null);  

    var new_html = request.responseText;
    var new_dom = document.createElement("div");
    // Strip the HTML down to the contents of the <body> tag.
    new_html = new_html.replace(/<!DOCTYPE.*?body\ id.*?>/, "");
    new_html = new_html.replace(/\/body>.*?<\/html>/, "");
    console.log("Strip HTML");
    new_dom.innerHTML = new_html;

    return new_dom;

}

As you can see, the request is currently synchronous. For reasons I'm sure you all know, this is bad. Using an asynchronous request doesn't get the job done, since the rest of the code begins executing before the page is finished downloading.

I think setTimeout() is what I need to be using. Something like this?

function getNewDOM(url) {
    console.log("getNewDOM()");
    // Get the page
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.send(null);  

    setTimeout(function() {

        var new_html = request.responseText;
        var new_dom = document.createElement("div");
        // Strip the HTML down to the contents of the <body> tag.
        new_html = new_html.replace(/<!DOCTYPE.*?body\ id.*?>/, "");
        new_html = new_html.replace(/\/body>.*?<\/html>/, "");
        console.log("Strip HTML");
        new_dom.innerHTML = new_html;

        return new_dom;

    }, 15000);

}

Problem is that I don't know a way to get that return value back to the original getNewDOM() function so that I can return it there. And even if I did, wouldn't it just wind up returning some undefined value in getNewDOM(), since the function in the timeout won't run until after getNewDOM() completes? And that would still leave me in the situation I'm in now.

I'm completely new to AJAX. I understand that there may be some simple ways to do with with jQuery, but I'd like to do it with vanilla Javascript if at all possible.

Upvotes: 1

Views: 2379

Answers (2)

Andreas
Andreas

Reputation: 21911

Instead of waiting 15 seconds you should use the readystatechange event

request.onreadystatechange = function() {
    if (request.readyState === 4 && request.status === 200) {
        // code which should be executed once the download has finished
        // ...
    }
}

Upvotes: 1

bfavaretto
bfavaretto

Reputation: 71939

I think setTimeout() is what I need to be using

No, because you never know when the async ajax request will be finished. What you need is to bind to the readystatechange event:

var request = new XMLHttpRequest();
request.onreadystatechange = function() {
    if (request.readyState==4 && request.status==200) {
        // Inside here is the only safe place to use request.responseText;
    }
}

Upvotes: 1

Related Questions