2016-08-13 2 views
0

У меня проблема с ожиданием существования элементов DOM.Async xhr и callback

Прежде всего, я делаю XHR к моему бэкэнду и получить некоторую информацию оттуда:

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

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

функции здесь:

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(); 
} 

Как вы можете видеть, что есть обратный вызов, который выполняется через 1 мс тайм-аута (я нашел этот трюк где-то в стеке некоторое время назад), но тогда другая функция не видит присоединенных элементов время от времени. Я также попытался

callback.call() 

не повезло до сих пор.

Может ли кто-нибудь посоветовать, как правильно подобрать элементы в этом случае?

+0

'loadTags (15, highlightAndSearchTags (searchParam, searchStr));' -> Это вызывает 'highlightAndSearchTags (searchParam, searchStr)' немедленно и проходит возврат значение ('undefined') для' loadTags' как 'callback' – Andreas

+0

нет необходимости в трюке setTimeout - ваша проблема в том, что @Andreas указал ... do' loadTags (15, function() {highlightAndSearchTags (searchParam , searchStr);}); 'вместо –

ответ

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

Как несколько замечаний, которые уже упоминалось, вы должны обернуть его в функцию, так что оно не называется когда вы вызываете функцию loadTags

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

Этот код будет выполнять вашу функцию highlightAndSearchTags немедленно и значение результата будет отправлен вместо обратного вызова, если вы хотите использовать его в качестве обратного вызова, вам нужно только передать имя функции, как:

loadTags(15, highlightAndSearchTags); 

Если вам нужно передать ваши searchParam и searchStr параметры, добавьте их в качестве параметров:

loadTags(15, highlightAndSearchTags, searchParam, searchStr); 

Когда ваши метки загружены Вы можете непосредственно вызвать ваш обратный вызов с параметрами searchParam и searchStr вы добавили в loadTags функции:

function loadTags(showedTagsLength, callback, searchParam, searchStr) { 
    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>"); 
       } 

      } 

      callback(searchParam,searchStr); 
     } 
    }; 
    xhr.send(); 
} 

Другого подход может быть также обернуть обратный вызов в прямоприменяемой анонимной функции. Это позволит предотвратить highlightAndSearchTags быть выполнено немедленно, так что вы можете назвать это позже, когда ваши теги загружены:

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

Зачем мне добавлять параметры обратного вызова в качестве параметров функции, которая должна выполнять обратный вызов? O.o – Andreas

+0

Я описал 2 подхода, добавив их в качестве параметров или обернув обратный вызов в самоисполняющейся анонимной функции. – HiDeo

+0

большое спасибо @HiDeo! –

1

Вы не передаете никакой функции обратного вызова. Вы немедленно вызываете функцию и передаете возвращаемое значение функции highlightAndSearchTags, которая не определена.

Анонимная функция может быть создана и передается как

loadTags(15,function(){ 
     highlightAndSearchTags(searchParam,searchStr) 
    }); 
Смежные вопросы