Переменные, установленные во время функции $.getJSON, доступны только в функции

Это может быть более проблематичным. Я пытаюсь установить объект JSON в функции $.getJSON, но мне нужно иметь возможность использовать этот объект за пределами обратного вызова.

var jsonIssues = {};  // declare json variable

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues not accessible here

Аналогичный вопрос, подобный этому, был задан в другом сообщении, и консенсус заключался в том, что все, что мне нужно делать с объектами JSON, должно выполняться внутри функции обратного вызова и не может быть доступно нигде. Неужели нет способа, чтобы я мог продолжать доступ к этому объекту JSON или манипулировать им вне обратного вызова $.getJSON? Как насчет возврата переменной или установки глобального?

Буду признателен за любую помощь. Это просто не кажется правильным...

UPDATE:

Попробовал установить для параметра $.ajax() async значение false и пропустил один и тот же код без везения. Код, который я пробовал, приведен ниже:

var jsonIssues = {};  // declare json variable

$.ajax({ async: false });

$.getJSON("url", function(data) {
    jsonIssues = data.Issues;
});

// jsonIssues still not accessible here

Кроме того, у меня было пару ответов о том, что глобальная переменная должна работать нормально. Я должен уточнить, что весь этот код находится в пределах $(document).ready(function() {. Чтобы установить глобальную переменную, нужно ли просто объявить ее перед document.ready? Таким образом:

var jsonIssues = {};

$(document).ready(function() {

  var jsonIssues = {};  // declare json variable

  $.getJSON("url", function(data) {
      jsonIssues = data.Issues;
  });

  // now accessible?
}

У меня создалось впечатление, что переменная, объявленная внутри document.ready, должна быть "глобально" доступной и модифицируемой в любой части document.ready, включая подфункции, такие как функция обратного вызова $.getJSON. Возможно, мне нужно будет прочитать обзор переменных javascript, но, похоже, нелегко достичь того, что я собираюсь сделать. Спасибо за все ответы.

ОБНОВЛЕНИЕ # 2: В комментариях к ответам ниже я использовал $.ajax вместо .getJSON и добился результатов, которые я хотел. Код ниже:

var jsonIssues = {};
    $.ajax({
        url: "url",
        async: false,
        dataType: 'json',
        success: function(data) {
            jsonIssues = data.Issues;
        }
    });

    // jsonIssues accessible here -- good!!

Несколько комментариев к моим ответам (и я ценю их всех). Моя цель заключается в том, чтобы сначала загрузить объект JSON со списком проблем, которые пользователь может удалить и сохранить. Но это делается через последующие взаимодействия на странице, и я не могу предвидеть, что пользователь захочет делать с объектом JSON в обратном вызове. Следовательно, необходимо сделать его доступным после завершения обратного вызова. Кто-нибудь видит недостаток в моей логике здесь? Серьезно, потому что может быть что-то, чего я не вижу...

Кроме того, я читал документацию .ajax() jQuery, и он говорит, что установка async на false "Загружает данные синхронно. Блокирует браузер, когда запросы активны. Лучше блокировать взаимодействие с пользователем другими способами, когда необходима синхронизация.

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

Ответ 1

$.getJSON является асинхронным. То есть код после вызова выполняется, а $.getJSON выбирает и анализирует данные и вызывает ваш обратный вызов.

Итак, учитывая это:

a();

$.getJSON("url", function() {
    b();
});

c();

Порядок вызовов a, b и c может быть либо a b c (что вам нужно в этом случае), либо a c b (скорее всего, произойдет).

Решение?

Синхронные запросы XHR

Сделать запрос синхронным, а не асинхронным:

a();

$.ajax({
    async: false,
    url: "url",
    success: function() {
        b();
    }
});

c();

Код структуры

Переместите вызов на c после вызова b:

a();

$.getJSON("url", function() {
    b();

    c();
});

Ответ 2

Помните, что когда вы предоставляете функцию обратного вызова, точка должна отложить выполнение этого обратного вызова до более позднего времени и немедленно продолжить выполнение следующего. Это необходимо из-за однопоточной модели исполнения JavaScript в браузере. Возможно принудительное синхронное выполнение, но он зависает браузером на весь период действия. В случае с чем-то вроде $.getJSON это означает, что браузер не перестает отвечать на запросы.

Другими словами, вы пытаетесь найти способ использования этой процедурной парадигмы:

var foo = {};

$.getJSON("url", function(data) {
  foo = data.property;
});

// Use foo here.

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

$.getJSON("url", function(data) {
  // Do something with data.property here.
});

"Что-то" может быть вызовом другой функции, если вы хотите, чтобы функция обратного вызова была простой. Важная часть заключается в том, что вы ожидаете завершения $.getJSON перед выполнением кода.

Вы даже можете использовать пользовательские события, чтобы код, который вы разместили после того, как $.getJSON подписывается на событие ProblemReceived, и вы поднимаете это событие в обратном вызове $.getJSON:

$(document).ready(function() {
  $(document).bind('IssuesReceived', IssuesReceived)

  $.getJSON("url", function(data) {
    $(document).trigger('IssuesReceived', data);
  });
});

function IssuesReceived(evt, data) {
  // Do something with data here.
}

Update:

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

$(document).ready(function() {
  $(document).bind('IssuesReceived', IssuesReceived)

  $.getJSON("url", function(data) {
    // I prefer the window.data syntax so that it obvious
    //  that the variable is global.
    window.data = data;

    $(document).trigger('IssuesReceived');
  });
});

function IssuesReceived(evt) {
  // Do something with window.data here.
  //  (e.g. create the drag 'n drop interface)
}

// Wired up as the "drop" callback handler on 
//  your drag 'n drop UI.
function OnDrop(evt) {
  // Modify window.data accordingly.
}

// Maybe wired up as the click handler for a
//  "Save changes" button.
function SaveChanges() {
  $.post("SaveUrl", window.data);
}

Обновление 2:

В ответ на это:

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

Причина, по которой вам следует избегать блокировки браузера с синхронными вызовами AJAX, заключается в том, что заблокированный поток JavaScript блокирует все остальное в браузере, включая другие вкладки и даже другие окна. Это означает, что нет прокрутки, навигации, нет ничего. Во всех смыслах и целях кажется, что браузер разбился. Как вы можете себе представить, страница, которая ведет себя таким образом, является значительной неприятностью для ее пользователей.

Ответ 3

возможно эта работа, работает со мной..:)

$variable= new array();

$.getJSON("url", function(data){
asignVariable(data);
}

function asignVariable(data){
$variable = data;
}

console.log($variable);

Надеюсь, это поможет вам. :)

Ответ 4

Вы можете приблизиться к этому с помощью promises:

var jsonPromise = $.getJSON("url")

jsonPromise.done(function(data) {
    // success
    // do stuff with data
});

jsonPromise.fail(function(reason) {
    // it failed... handle it
});

// other stuff ....

jsonPromise.then(function(data) {
    // do moar stuff with data
    // will perhaps fire instantly, since the deferred may already be resolved.
});

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

Ответ 5

"Но это делается через последующие взаимодействия на странице, и я не могу предвидеть, что пользователь захочет делать с объектом JSON в обратном вызове".

Обратный вызов - это ваша возможность установить экран для взаимодействия пользователя с данными.

Вы можете создать или открыть HTML для пользователя и настроить дополнительные обратные вызовы.

В большинстве случаев ни один из ваших кодов не будет запущен. Программирование страницы Ajax - это размышление о том, какие события могут произойти, когда.

Есть причина, по которой это "Ajax", а не "Sjax". Там есть причина, из-за которой боль меняется от асинхронного до синхронизации. Он ожидал, что вы сделаете асинхронную страницу.

Программирование, управляемое событиями, может быть разочаровывающим вначале.

Я сделал вычислительные интенсивные финансовые алгоритмы в JS. Даже тогда, это то же самое - вы разбиваете его на маленькие части, а события - это таймауты.

Анимация в JavaScript также управляется событиями. Фактически, браузер даже не покажет движение, если ваш script не отменит управление повторно.