简体   繁体   中英

wait for AJAX response before continuing

So I see this asked many times but none of the answers I found work. Basically I have a AJAX function that can be called by many other functions. My issue is after I sometimes need to run code on the loaded element, such as add event listeners. Of course, the script doesn't wait for the element to finish loading do I get a "document.getElementById(...) is null" error. I have tried call backs, doesn't change anything. I tried synchronous AJAX. It's decrepit. and didn't work. I have tried running JavaScript in the response data. As anyone here should know, doesn't work.

So I'm missing something. Is there another way to load dynamic data without reloading the page? is there a way to force the code to wait? What is the solution to this?

My Code that doesn't work:

function ajax_call(page, target_tag, data)
{
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function()
    {
        if (xhttp.readyState == 4 && xhttp.status == 200)
        {
            target_tag.innerHTML = xhttp.responseText;
        }
    };
    xhttp.open("POST", page);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send(data);
}

function edit_gallery(gallery)
{
    var target_tag= document.createElement("div");
    target_tag.style.position= "fixed";
    target_tag.style.top= "10px";
    target_tag.style.backgroundColor= "#FFFFFF";
    target_tag.style.padding= "10px";
    target_tag.style.margin= "0px auto";
    target_tag.id= "gallery_edit_window";

    document.getElementsByTagName("BODY")[0].appendChild(target_tag);
    ajax_call("/everythingapps/imagegallery/edit_gallery.php", target_tag, gallery);
    document.getElementById('gallery_save_btn').addEventListener('click', function() {save_gallery();});
}

function save_gallery()
{
    alert('test');
}

So my issue is in this park of the code:

ajax_call("/everythingapps/imagegallery/edit_gallery.php", target_tag, gallery);
document.getElementById('gallery_save_btn').addEventListener('click', function() {save_gallery();});

So any ideas? No JS libraries.

Edit: I made several attempts at call backs. Honestly I'm have trouble understanding them. Here is my last attempt:

function testing(callback)
{
    callback("/everythingapps/imagegallery/edit_gallery.php", target_tag, gallery)
}
testing(ajax_call);
document.getElementById('gallery_save_btn').addEventListener('click', function() {save_gallery();});

Callbacks are meant to be called after you get a response from the server. You've got it backwards. You actually need to pass your callback function as an argument to your ajax_call . Then in the onreadystatechange event you invoke the callback once you receive the server response.

Like this:

function ajax_call(page, target_tag, data, callbackFn)
{
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function()
    {
        if (xhttp.readyState == 4 && xhttp.status == 200)
        {
            target_tag.innerHTML = xhttp.responseText;
            callbackFn(); //INVOKE THE CALLBACK FUNCTION
        }
    };
    xhttp.open("POST", page);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send(data);
}

Then when you call the ajax_call function, you would pass in a callback function as the last argument which would update your element:

ajax_call("/everythingapps/imagegallery/edit_gallery.php", target_tag, gallery, function() {
    //ajax call has completed so now we can update the element
    document.getElementById('gallery_save_btn').addEventListener('click', function() {save_gallery();})
});

An additional change you can make to make things even more flexible and make your ajax call more generic is to pass the server response to the callback function. You'd want to do this if you have multiple targets you want to update.

callbackFn(xhttp.responseText); //INVOKE THE CALLBACK FUNCTION WITH DATA

Then you can eliminate target_tag as an argument and do this:

ajax_call("/everythingapps/imagegallery/edit_gallery.php", gallery, function(data) {
    //ajax call has completed so now we can update TWO ELEMENTS
    target_tag.innerHTML = data;
    document.getElementById('gallery_save_btn').addEventListener('click', function() {save_gallery();})
});

So there are a few things going on here.

First off, callbacks. They can be tricky! I've found to best get your head around them, it's all about visualizing what's going on in the code by abstracting the code out of the situation. Take the following (and bear with me):

You're shopping for socks on Amazon. Once you get the socks you want, you'll wear them around town and look super flashy (that much is certain). So you're on your computer and you find the nicest socks you want, and click 'Buy'. Bam! They'll be here in 2 days.

That's great, but what now? You want to get on with your life for the next 2 days! When those socks come to your door, you'll put them on - but until then, it's business as usual.

Callbacks are just like this. They do something (like order socks on Amazon), and instead of freezing up your code until whatever they requested comes back, the code moves on. A callback, by definition, is a set of tasks that the program executes whenever an asynchronous call is made (so in this example, the 'callback' would be to put on the socks and wear them around town).

So here's a thing: you need to make sure that everything that depends on the data coming back (in the example, the socks that come to your door) stay in the callback function. To continue this ridiculous example, let's say you want to do the following with your socks:

1) Wear them driving to the gym 2) Wear them at the gym 3) Wear them on your way back from the gym

You make this list of things to do with your new socks. What's the common theme in the list? You have the socks ! Without them, you couldn't do any of these things (at least, how they're specified in the list).

How does this lengthy response relate to your code? Well, take a look at the steps your taking after you make an AJAX call, and what each step depends on. Basically, if any of the code assumes that you have whatever's in that PHP file, you need it in your callback function.

Best of luck!

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