简体   繁体   中英

XMLHttpRequest - when returning responseText to another function, it returns undefined

SOLVED. I changed my code into this:

function init() {
    //preloadImages();
    getContent('events', 'events');
    getContent('content', 'main');
}

function loadingScreen(start) {
    var loadingSpan = document.getElementById('loading');
    if (start == true) {
            loadingSpan.innerHTML = '<p>Loading...<br><img src="images/loading.gif"></p>';
    }
    else {
            loadingSpan.innerHTML = '';
    }
}

function getContent(what, where) {
    if (what == 'content') {
            loadingScreen(true);
            var ranLoad = true;
    }
    var toSet = document.getElementById(what);
    var location = "content/" + where + ".txt";
    var request = new XMLHttpRequest;
    request.open("GET", location, true);
    request.onreadystatechange = function(){
            if (request.readyState == 4 && request.status == 200){
                    toSet.innerHTML = request.responseText;
                    if (ranLoad==true){
                            loadingScreen(false);
                    }
            }
    }
    request.send(null);
}
window.onload = init;

tl;dr or long-winded - see the code and the results below.

So. I am building a small webpage for a friend, and I decided to try out a technique where instead of writing the content directly in the webpage, I will use XMLHttpRequest to retrieve content (in the same domain), and place them in the content , where it will be updated by javascript, when people click on a different anchor. Well, I came across a roadbump. When I created the functions for getting the content (setEvents and setContent), where it creates a variable and calls a function for setting the variable (getMarkup), when the function was called, and the return statement was executed, it returns undefined. I found a thread similar, but their solution was to add the innerHTML statement DIRECTLY in the getMarkup function. I don't want to do that.

Here's the code and the results:

Edit : Esailija suggested that I should have just posted the code. To me it was a tad bit easier to just take the image, but here it is:

function init() {
    //preloadImages();
    setEvents();
    setContent('main');
}

function setEvents() {
    var eventDiv = document.getElementById("events");
    var eventContent = getMarkup("content/events.txt");
    eventDiv.innerHTML = eventContent;
}

function setContent(which) {
    loadingScreen('start');
    var contentDiv = document.getElementById('content');
    location_ = "content/" + which + 'txt';
    //var contentContent = getMarkup('location');
    //contentDiv.innerHTML = contentContent;
    loadingScreen('stop');
}

function loadingScreen(action) {
    var loadingSpan = document.getElementById('loading');
    loadingSpan.innerHTML = "Test";
    if (action == 'start') {
        loadingSpan.innerHTML = '<p>Loading...<br><img src="images/loading.gif"></p>';
    }
    if (action == 'stop') {
        loadingSpan.innerHTML = '';
    }
}

function getMarkup(where) {
    var filerequest = new XMLHttpRequest();
    filerequest.open("GET", where, true);
    filerequest.onreadystatechange = function() {
        if (filerequest.readyState == 4 && filerequest.status == 200) {
            var test = document.getElementById("events");
            var reply = filerequest.responseText;
            //Doesn't work
            return reply;
            //Works just fine
            //test.innerHTML = reply;
        }
    };
    filerequest.send(null);
}
window.onload = init;

When I do the innerHTML instead of return it shows "Test TEST ", and when I do return instead of innerHTML, it shown "undefined".

I really don't want to do the innerHTML part of it, so is there a workaround to make that return statement work?

Are you familiar with callbacks? Open up Firebug and put a breakpoint on your return reply; line - notice the call stack. The function where you have return reply; is not getMarkup .

Basically you're going to have to restructure your code a little. I would have getMarkup take an additional parameter - the DOM element to which you want to set its innerHTML value.

It seems that you don't quite understand how ajax works.
Once you call your getMarkup function, you send an ajax request and tell the browser to use the function after onreadystatechange to handle the reply. So actually when the reply is back, it's not your other functions like setContent that are calling that handler but the browser. That's why the return doesn't work.

Also when you call something like var contentContent = getMarkup('location'); , as getMarkup has no explicit return value, so by default contentContent gets undefined . You may think that it should get the return value inside your anonymous function but that's not the case. The getMarkup function returns immediately but the handler will be called only when the ajax response comes.

If you want to make that nice, you will have to do something extra like: you only have one ajax handler like you did. Once a function called that ajax function it register its callback into a queue and when the response is back the queue is popped and the values are then updated. This would take some time for you to build this mechanism or you may need to check how the jQuery Ajax Queue works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM