Правильный способ ожидания возврата ajax (я не хочу использовать обработчик успеха).
Возможный дубликат:
Как я могу получить jQuery для выполнения синхронного, а не асинхронного запроса AJAX?
как ждать возвращения ajax-запроса
Услышьте меня. Я полностью понимаю этот сегмент кода.
$.getJSON(someURL, function(data){
//do something with my data
})
.success(function () {
//Call what you want on success
})
Это кажется прекрасным, если мне просто нужно сделать одно действие, которое довольно статично. Однако, если я хочу быть менее ограниченным, например, это
function my_func(){
$.getJSON(someURL, function(data){
//do something with my data... like modify an array or the dom
})
}
Теперь драйвер
my_func();
//Now I want to call a function that relies on the data that my_func brought into the script.
Что-то не так с тем, как я кодирую свой script, если я хочу сделать это вот так? Или я просто пропустил какой-то потрясающий встроенный метод?
Ответы
Ответ 1
Я вижу два возможных пути jQuery-ish.
Первым будет использование другого обратного вызова, который может быть передан в my_func
:
function my_func(callback) {
$.getJSON(someUrl, function(data) {
// ...do stuff ...
if ($.isFunction(callback)) { callback(data); }
});
}
my_func(function(data) {
// ..do more stuff..
});
Второй способ - создать настраиваемое событие, которое запускается внутри my_func
, и его можно прослушивать извне:
function my_func() {
$.getJSON(someUrl, function(data) {
$(document).triggerHandler('my_func:data-received', [data]);
});
}
$(document).on('my_func:data-received', function(event, data) {
// ...do stuff...
});
my_func();
Я настоятельно рекомендую использовать async: false
только в том случае, если это абсолютно необходимо.
Еще один (очень аккуратный) способ справиться с этим - это объект jQuery.Deferred:
function my_func() {
var d = new $.Deferred();
$.getJSON(someUrl, function(data) {
d.resolve(data);
});
return d;
}
my_func().done(function(data) {
// ...do stuff...
});
Ваша функция возвращает объект, который позволяет регистрировать обратные вызовы. Внутри функции вам просто нужно обязательно вызвать resolve
для вызова всех зарегистрированных обработчиков обратных вызовов done
.
Ответ 2
Тогда есть объект XHR:
var jqXHR = $.getJSON(someURL);
Вы можете получить к нему доступ в любом месте после его определения:
jqXHR.always(function() {
alert('JSON IS COMLETE');
});
jqXHR.done(function(data) {
//do something with the returned data if success!
});
jqXHR.fail(function(jqXHR, textStatus) {
alert('JSON FAILED : '+textStatus);
});
FIDDLE
Вы можете даже сделать что-то вроде этого:
$("#button").on('click', Myfunc);
function Myfunc() {
var jqXHR = runAjax();
jqXHR.done(function(data) {
alert($.parseJSON(data));
$("#result").html('JSON IS DONE');
});
}
function runAjax() {
return $.getJSON(someURL);
}
FIDDLE
Ответ 3
Вероятно, вы передадите свою функцию, которая работает с данными, в my_func()
.
// v--------receive a callback
function my_func(callback_fn){
$.getJSON(someURL, callback_fn); // use the callback as the getJSON callback
}
то...
my_func(function(data) {
// do something with data
})
... или если функция, которую вы хотели вызвать, была именованной функцией, тогда, конечно, вы передадите ее по имени...
my_func(someOtherFunction)
В любом случае ваша функция my_func()
будет использовать ее в качестве обратного вызова к вызову $.getJSON
, который будет вызывать его при поступлении данных.