Могу ли я объявить неглобальную переменную для хранения асинхронных значений?

#javascript #jquery #ajax #scope

#javascript #jquery #ajax #область видимости

Вопрос:

У меня есть несколько файлов JavaScript. У меня есть функция JS, которая запускается при загрузке и содержит несколько вызовов AJAX. Каждый вызов AJAX выполняет обратный вызов (а также увеличивает синхронный счетчик):: myArray.push('somevalue');

чтобы я мог проверить, когда завершатся все вызовы AJAX (для этого JS-файла).

Есть ли способ, которым я могу избежать объявления myArray в качестве глобальной переменной, позволяя асинхронным обратным вызовам вставляться в этот массив?

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

1. Вам придется переходить myArray к каждому вызову.

2. Если вы передаете myArray для каждого вызова, он все равно будет ссылаться на эту переменную? Поскольку JS выполняет передачу по значению, асинхронный вызов не будет искать исходную переменную [reference of]?

3. Просто создайте область, которая не является глобальной, jQuery document.ready или IIFE сделают это, и установите массив в той же или более высокой области, чем вызовы ajax.

4. Если вы передаете массив, то значение является ссылкой на массив .

5. у вас есть 2 хороших решения в комментариях здесь, но мой вопрос: почему вы беспокоитесь о том, чтобы сделать этот массив глобальным?

Ответ №1:

Если вы хотите выполнить некоторый код после выполнения заданного количества запросов AJAX, используйте $.when .

Если вы используете myArray исключительно для того, чтобы узнать, когда запросы завершены, вы можете удалить его. Если вы используете ее для хранения результата каждого запроса, вы можете сохранить ее в той же области, что и запросы, а затем получить к ней доступ в done обработчике. Попробуйте это:

 var myArray = [];

var ajax1 = $.ajax({
    url: '/foo/',
    success: function(data) {
        myArray.push(data);
    });
});

var ajax2 = $.ajax({
    url: '/bar/',
    success: function(data) {
        myArray.push(data);
    });
});

$.when(ajax1, ajax2).done(function() {
    // both requests complete
    // myArray will contain the data of both requests at this point...
    for (var i = 0; i < myArray.length; i  ) {
        console.log(myArray[i]);
    }
});
  

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

1. Я не был сторонником отказа, но я думаю, это потому, что вы не рассмотрели ситуацию, о которой спрашивал ОП, может ли он иметь массив, не являющийся глобальным, и назначать ему каждый обратный вызов.

2. Это действительно решает эту проблему — если единственная цель массива — узнать, когда завершатся запросы, тогда массив больше не требуется. Если она используется для хранения результата каждого запроса, она может находиться в той же области, что и сами запросы (т.е. не глобальный), а затем доступ к нему в done обработчике.

3. Я бы объяснил это и проголосовал за лучшее решение, о котором я только что узнал .when() пару месяцев назад и очистил с его помощью так много кода

4. @ScottSelby да, это действительно удобный метод для управления на тяжелом сайте AJAX. Спасибо за предложения.

5. К сожалению, моя версия jQuery немного отстает, но в настоящее время я рассматриваю возможность обновления.

Ответ №2:

Объявите переменную, доступную только в той области, в которой вы ее хотите (например, внутри функции).

Что-то вроде:

 var ajaxCalls = function() {
    var myArray = [];

    var ajax1 = $.ajax({
        url: 'foo.com',
        success: function(data) {
            myArray.push(data);
        });
    });

    // do more AJAX stuff

    $.when(ajax1, ..., ).done(function() {
        // make sure all requests are complete
        // do stuff with the completed array
    });
};
  

Поскольку JavaScript имеет функциональную область видимости, ваша переменная myArray не будет глобальной, но она будет доступна в рамках обратных вызовов ajax. Надеюсь, это поможет!