jQuery — синхронное выполнение

#jquery #ajax #json

#jquery #ajax #json

Вопрос:

Мне нужно сделать несколько вызовов API YouTube через AJAX для получения видеоинформации в формате JSON.

Каждый из вызовов может обрабатываться синхронно, но после получения всех данных его необходимо обработать отобразить.

Как я могу гарантировать, что функция обработки не вызывается до получения всех данных? Моим текущим решением было вызывать функцию AJAX повторно, но я чувствую, что есть гораздо лучшее решение.

Любая помощь была бы очень признательна.

     var categoryWrapper,categories;
    var catCnt=0;

    function initialiseVideoLibrary() {
        categories=new Array("health","hiv","education","volunteering");
        getYouTubeData();
    }

    function getYouTubeData() {

        ytJsonUrl = "https://gdata.youtube.com/feeds/api/users/vsomediauk/uploads/-/"   categories[catCnt]   "?v=2amp;alt=jsoncamp;max-results=5amp;orderby=relevance";

        $.ajax({
            type: "GET",
            url: ytJsonUrl,
            cache: false,
            dataType:'jsonp',
            success: function(ytJsonResponse){
                if (catCnt < categories.length) {
                showCategory(categories[catCnt],ytJsonResponse);
                    getYouTubeData();
                    catCnt  ;
                } else {
                    tabVideos();
                }
            }

        });
    }

    function showCategory(cat,ytResponse) {

        categoryWrapper = $('<div></div>').addClass('category');

        $(categoryWrapper).append($('<h3></h3>').text(cat));

        contentDiv = $('<div></div>').addClass('content');

        $.each(ytResponse.data.items,function(i,video) {
            videoWrapper = $('<div></div>').addClass('video');
            $(videoWrapper).append($('<p></p>').text(video.id));
            $(videoWrapper).append($('<p></p>').text(video.title));
            $(videoWrapper).append($('<img></img>').attr('src',video.thumbnail.sqDefault));
            $(contentDiv).append(videoWrapper);
        });

        $(categoryWrapper).append(contentDiv);
        $("#videolist").append(categoryWrapper);

    }

    function tabVideos() {
        $("#videolist").tabulation({tabAlignment : "right", titleTag : "h3", tabPosition : "top"});
    }
  

Ответ №1:

Это было бы отличным использованием jQuery.Deferred .

Просто сохраните возвращаемые значения вызовов jQuery.ajax , а затем передайте их jQuery.when .

Редактировать: как я только что заметил, это не очевидно из документации, я подумал, что хотел бы отметить, что вы можете передать массив deferred s when , используя следующий синтаксис:

 $.when.apply(null, ajaxReturnValueArray).then(function() {
    tabVideos(); // Assuming this is the method you wanted to call
});
  

Ответ №2:

Я не уверен, но вы можете попробовать со следующим изменением :

 function getYouTubeData() {

    ytJsonUrl = "https://gdata.youtube.com/feeds/api/users/vsomediauk/uploads/-/"   categories[catCnt]   "?v=2amp;alt=jsoncamp;max-results=5amp;orderby=relevance";

    $.ajax({
        type: "GET",
        url: ytJsonUrl,
        cache: false,
        async: false,
        dataType:'jsonp',
        success: function(ytJsonResponse){
            if (catCnt < categories.length) {
            showCategory(categories[catCnt],ytJsonResponse);
                getYouTubeData();
                catCnt  ;
            } else {
                tabVideos();
            }
        }

    });
}
  

Ответ №3:

Проверьте .ajaxStop() , что-то подобное может сработать (извините, непроверено!)

 var categoryWrapper,categories;

function initialiseVideoLibrary() {
    categories=new Array("health","hiv","education","volunteering");
    getYouTubeData();
}

function getYouTubeData() {

        $.each(categories, function(index, value) {
            ytJsonUrl = "https://gdata.youtube.com/feeds/api/users/vsomediauk/uploads/-/"   value   "?v=2amp;alt=jsoncamp;max-results=5amp;orderby=relevance";

            $.ajax({
                type: "GET",
                url: ytJsonUrl,
                cache: false,
                dataType:'jsonp',
                success: function(ytJsonResponse){
                    showCategory(value,ytJsonResponse);
                }

            });
        });
}

function showCategory(cat,ytResponse) {

    categoryWrapper = $('<div></div>').addClass('category');

    $(categoryWrapper).append($('<h3></h3>').text(cat));

    contentDiv = $('<div></div>').addClass('content');

    $.each(ytResponse.data.items,function(i,video) {
        videoWrapper = $('<div></div>').addClass('video');
        $(videoWrapper).append($('<p></p>').text(video.id));
        $(videoWrapper).append($('<p></p>').text(video.title));
        $(videoWrapper).append($('<img></img>').attr('src',video.thumbnail.sqDefault));
        $(contentDiv).append(videoWrapper);
    });

    $(categoryWrapper).append(contentDiv);
    $("#videolist").append(categoryWrapper);
}

$("#videolist").ajaxStop(function() {
    $(this).tabulation({tabAlignment : "right", titleTag : "h3", tabPosition : "top"});
});
  

Ответ №4:

Я думаю, что наиболее чистым способом было бы сделать вызов ajax синхронным, а затем вызвать getYouTubeData() последовательно в цикле for .

getYouTubeData() должен быть:

 function getYouTubeData(cat) {

    ytJsonUrl = "https://gdata.youtube.com/feeds/api/users/vsomediauk/uploads/-/"  cat  "?v=2amp;alt=jsoncamp;max-results=5amp;orderby=relevance";

    $.ajax({
        type: "GET",
        url: ytJsonUrl,
        cache: false,
        async: false, //this is to make tha ajax call synchronous
        dataType:'jsonp',
        success: function(ytJsonResponse){
            showCategory(cat,ytJsonResponse);
        }
    });
}
  

И вы могли бы вызвать его следующим образом:

 for (var iC = 0; iC < categories.length; iC  ){
    getYouTubeData(categories[iC]);
}
tabVideos();
  

Таким образом, tabVideos() будет вызван после завершения всех вызовов getYouTubeData() .