возвращает данные из вложенного запроса jquery ajax get

#javascript #jquery #ajax #get

#javascript #jquery #ajax #получить

Вопрос:

У меня есть 2 вызова Get API JAVASCRIPT, которые я выполняю с помощью JQUERY. Я хочу добавить HTML, который я создаю во время второго вызова DOM.

Первый вызов захватывает некоторые данные. Я перебираю длину этих данных, делая второй вызов для каждого индекса.

Во время второго вызова я создаю HTMLContent.

Как только все вызовы выполнены, я добавляю HTMLContent в DOM.

Я изо всех сил пытаюсь вернуть HTMContent обратно в пределах первого вызова, так как я хочу добавить DOM только тогда, когда он будет полностью создан. И вне for созданного мной цикла.

Я знаю, что мог бы добавить done из 2-го вызова, но мне бы очень хотелось знать, как его вернуть.

Я подумал, возможно, мне нужно создать обещание, но не уверен, что это поможет, так как область по-прежнему будет содержаться во второй .done функции запроса get.

Это то, что у меня есть до сих пор.

 var gallery = (function($){

    var init,
        firstGetCall,
        secondGetCall,
        HTMLContent = '';

    init = function(){
        // Make first call
        firstGETCall();
    };

    // Declare firstGETCall func
    firstGETCall = function(){
        $.ajax({
            url: 'http://example.com/data.json',
            type: 'GET',
            data: {
                numberOfItems: 10
            }
        })
        .done(function(data) {

            //  Cycle through each data element
            for (var i = 0; i < data.length; i  ) {
                // Make second call
                secondGetCall(data[i]);
            };
        })
        .fail(function(error) {
            console.log(error);
        });
        // I want to append the DOM here with the conplete HTMLContent - built up of 10 x <div><img... elements
        // However I'm stuck as to how to return the complete HTMLContent
    };

    // Declare secondGetCall func
    secondGetCall = function(singleData) {

        $.ajax({
            url: 'http://example.com/data-2.json',
            type: 'GET',
            data: {
                type: singleData
            }
        })
        .done(function(data) {

            // Build HTMLContent
            HTMLContent = '<div><img src="'   data.image   ' title="'   data.subTitle   ' alt="Photo"></div>';
            // I do not want to append the DOM here
            // return HTMLContent doesn't work
        })
        .fail(function(error) {
            console.log(error);
        });
    };

    return {
        init: init
    };

})(jQuery);


gallery.init(jQuery);
 

Ответ №1:

Сначала самый важный момент:

Я хочу добавить сюда DOM…

В любом случае, вы ничего не можете сделать в том месте, где вы разместили приведенный выше комментарий!

Поскольку Ajax работает асинхронно (если вы не укажете обратное, но это настоятельно не рекомендуется), любой оператор в указанном вами месте будет выполнен через несколько микросекунд после $.ajax запуска, так что пройдет много времени, прежде чем будет собран весь ваш HTML.

Теперь это тоже кажется странным:

Я изо всех сил пытаюсь вернуть HTMContent обратно в пределах первого вызова

Во-первых, потому что, опять же из-за асинхронного режима, вы не можете ожидать возврата чего-либо из .done() вызова Ajax.
Но также и потому, что я не понимаю, почему вы хотите «вернуть» данные, которые уже доступны на более высоком уровне. На самом деле вам нужно только получать уведомления, когда они будут доступны.

С другой стороны, я полностью согласен, что лучше добавлять HTML в DOM только один раз, чтобы сократить затраты времени.

Затем, чтобы это сработало, моя первая мысль такова: почему бы просто не иметь уникальную серверную функцию, возвращающую весь набор необходимых данных, а не два разных?

Однако, в случае, если по какой-то причине это действительно невозможно, вы можете фактически заставить вызовы Ajax работать синхронно (но, опять же, вам следует избегать этого).
В этом случае вам необходимо :

  1. В вашей secondGetCall() функции слегка измените оператор .done() body, чтобы добавлять новые данные HTMLContent , а не просто устанавливать их : HTMLContent = '<div>...</div>' ; .
  2. В каждом из двух вызовов Ajax добавьте async: false к объекту Ajax.
  3. Напишите инструкцию для добавления HTMLContent в DOM в том месте, где вы написали комментарий об этом.

Комментарии:

1. Спасибо @cFreed — похоже, я хочу сохранить его асинхронным. Как мне изменить то, что мне нужно для этого? Опять же, изо всех сил пытаюсь понять, где и как я могу поместить уведомление, чтобы сообщить, когда все будет завершено и будет создан HTMLContent.

2. и в вашем ответе в пункте 1. Если я не ошибаюсь, я добавляю (объединяю) новые данные с помощью = присваивания

3. @fidev Сначала отвечаю на ваш последний комментарий: да, я предлагаю последовательно заполнять HTMLContent , добавляя каждую новую часть, затем (пункт 3) использовать фактический весь HTML-текст для добавления в DOM. Что вас здесь озадачивает?

4. @fidev Относительно вашего предыдущего комментария: труднее получить хороший ответ. Если вы хотите сохранить его асинхронным, единственный другой способ, который я могу придумать, это что-то вроде: 1) добавьте .complete() обработчик в secondGetCall() , где вы увеличиваете счетчик (ранее определенный в верхней части функции); 2) добавьте .complete() обработчик в firstGETCall() , где вы добавляете HTML к DOM, когда счетчик ==желаемое количество элементов . Но вы должны понимать, что это просто еще один способ синхронной работы! Поэтому я еще раз предлагаю вам рассмотреть возможность работы раз и навсегда на уровне сервера.