javascriptjqueryasynchronousjquery-callback

Async xhr and callback


I have a problem with waiting for DOM elems to exist.

First of all, I make an XHR to my backend and get some info from there:

$(document).ready(function() {
    var searchParam, searchStr;
    // some values to vars

    loadTags(15,highlightAndSearchTags(searchParam,searchStr));
});

The functions are here:

function highlightAndSearchTags(searchParam, searchStr) {
    if (searchParam == 'tags') {
        var selectedTags = searchStr.split(',');
        console.log($("#my_favorite_latin_words").children().length); // sometimes returns 0, sometimes returns number of <span> in the div (see loadTags())
        for (var i = 0; i < selectedTags.length; i++) {
            $("#" + selectedTags[i]).toggleClass("tag-selected");
        }
    }
}

function loadTags(showedTagsLength, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', apiUrl + "tags/", true);
    xhr.withCredentials = true;
    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            if (xhr.status != 200) {
                console.log(xhr.responseText);
            }
            else {
                tagList = JSON.parse(xhr.responseText);
                tagList = tagList.results;

                for (var i = 0; i < showedTagsLength; i++) {
                    $("#my_favorite_latin_words").append("<span id=\'" + tagList[i].tag_pk + "\'>" + tagList[i].name + "</span>");
                }

            }
            setTimeout(callback, 1); //found this trick somewhere on stackoverflow
        }
    };
    xhr.send();
}

As you can see there is a callback which is executed after 1ms timeout (I found this trick somewhere on stack a while ago), but then another function does not see the appended elements from time to time. I have also tried

callback.call()

with no luck so far.

Can anybody advise how to wait for the elements correctly in this case?


Solution

  •  loadTags(15,function(searchParam,searchStr){highlightAndSearchTags(searchParam,searchStr)});
    

    As multiple comments already mentioned, you have to wrap it into a function so that it isnt called when you call the loadTags function