Переменные, установленные во время функции $.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 не отменит управление повторно.
Ответ 6
Вы просто сталкиваетесь с проблемами определения области.
Короткий ответ:
window.jsonIssues = {}; // or tack on to some other accessible var
$.getJSON("url", function(data) {
window.jsonIssues = data.Issues;
});
// see results here
alert(window.jsonIssues);
Длинные ответы:
Проблема определения в Javascript
Проблема с закрытием Javascript