Jak mogę zmusić jQuery do wykonania synchronicznego, a nie asynchronicznego żądania Ajax?
Mam widget JavaScript, który zapewnia standardowe punkty rozszerzeń. Jedną z nich jest funkcja beforecreate
. Powinien zwrócić false
, aby zapobiec utworzeniu elementu.
Dodałem wywołanie Ajax do tej funkcji przy użyciu jQuery:
beforecreate: function (node, targetNode, type, to) {
jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
function (result) {
if (result.isOk == false)
alert(result.message);
});
}
Ale chcę, aby mój widget nie tworzył elementu, więc powinienem zwrócić false
w funkcji matki, a nie w wywołaniu zwrotnym. Czy istnieje sposób na wykonanie synchronicznego żądania AJAX przy użyciu jQuery lub innego API w przeglądarce?
13 answers
Z jQuery documentation: podajesz asynchroniczną opcję false, aby uzyskać synchroniczne żądanie Ajax. Wtedy twój callback może ustawić pewne dane, zanim twoja matka zacznie działać.
Oto jak wyglądałby Twój kod, gdyby został zmieniony zgodnie z sugestią:
beforecreate: function (node, targetNode, type, to) {
jQuery.ajax({
url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
success: function (result) {
if (result.isOk == false) alert(result.message);
},
async: false
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-21 12:20:02
Możesz umieścić konfigurację Ajax jQuery w trybie synchronicznym, wywołując
jQuery.ajaxSetup({async:false});
A następnie wykonaj połączenia Ajax używając jQuery.get( ... );
Następnie włącz go ponownie raz
jQuery.ajaxSetup({async:true});
Wydaje mi się, że działa to tak samo, jak sugeruje to @Adam, ale może to być pomocne dla kogoś, kto chce zmienić swoją jQuery.get()
lub jQuery.post()
na bardziej rozbudowaną składnię jQuery.ajax()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-30 21:25:00
Doskonałe rozwiązanie! Zauważyłem, gdy próbowałem go zaimplementować, że jeśli zwróciłem wartość w klauzuli sukcesu, wróciła jako niezdefiniowana. Musiałem zapisać go w zmiennej i zwrócić tę zmienną. Jest to metoda, którą wymyśliłem:
function getWhatever() {
// strUrl is whatever URL you need to call
var strUrl = "", strReturn = "";
jQuery.ajax({
url: strUrl,
success: function(html) {
strReturn = html;
},
async:false
});
return strReturn;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-30 21:25:14
Wszystkie te odpowiedzi pomijają to, że wywołanie Ajax z async: false spowoduje zawieszenie przeglądarki do czasu zakończenia żądania Ajax. Korzystanie z biblioteki kontroli przepływu rozwiąże ten problem bez rozłączania przeglądarki. Oto przykład z Frame.js :
beforecreate: function(node,targetNode,type,to) {
Frame(function(next)){
jQuery.get('http://example.com/catalog/create/', next);
});
Frame(function(next, response)){
alert(response);
next();
});
Frame.init();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-21 12:23:10
function getURL(url){
return $.ajax({
type: "GET",
url: url,
cache: false,
async: false
}).responseText;
}
//example use
var msg=getURL("message.php");
alert(msg);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-25 15:34:38
Pamiętaj, że jeśli wykonujesz między domenowe wywołanie Ajax (używając JSONP ) - nie możesz zrobić tego synchronicznie, flagaasync
zostanie zignorowana przez jQuery.
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
Dla połączeń JSONP można użyć:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-30 07:24:05
Uwaga: nie powinieneś używać asynchronizacji z tego powodu:
Począwszy od Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchroniczne żądania w głównym wątku zostały wycofane ze względu na negatywny wpływ na doświadczenie użytkownika.
Chrome ostrzega nawet o tym w konsoli:
Synchroniczne XMLHttpRequest w głównym wątku jest przestarzałe ze względu na jego szkodliwy wpływ na doświadczenie użytkownika końcowego. Aby uzyskać więcej pomocy, sprawdź https://xhr.spec.whatwg.org/.
To może złamać stronę, jeśli robisz coś takiego, ponieważ może przestać działać lada dzień.
Jeśli chcesz zrobić to w sposób, który nadal wydaje się synchroniczny, ale nadal nie blokuje, powinieneś użyć async / wait I prawdopodobnie również ajax, który jest oparty na obietnicach, takich jak NOWY Fetch API
async function foo() {
var res = await fetch(url)
console.log(res.ok)
var json = await res.json()
console.log(json)
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 20:04:51
Użyłem odpowiedzi udzielonej przez Carcione i zmodyfikowałem ją na JSON.
function getUrlJsonSync(url){
var jqxhr = $.ajax({
type: "GET",
url: url,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
function testGetUrlJsonSync()
{
var reply = getUrlJsonSync("myurl");
if (reply.valid == 'OK')
{
console.dir(reply.data);
}
else
{
alert('not valid');
}
}
Dodałem dataType z 'JSON' i zmieniłem .responseText do responseJSON.
Odzyskałem również status używając właściwości statusText zwracanego obiektu. Zauważ, że jest to stan odpowiedzi Ajax, a nie to, czy JSON jest poprawny.
Back-end musi zwracać odpowiedź w poprawnym (dobrze uformowanym) JSON, w przeciwnym razie zwracany obiekt będzie niezdefiniowany.
Są dwa aspekty, które należy wziąć pod uwagę, odpowiadając na pierwotne pytanie. Jeden mówi Ajaxowi, aby działał synchronicznie (ustawiając async: false), a drugi zwraca odpowiedź za pomocą instrukcji return funkcji wywołującej, a nie do funkcji zwrotnej.
Próbowałem też z postem i zadziałało.
Zmieniłem GET to POST i dodałem Dane: postdata
function postUrlJsonSync(url, postdata){
var jqxhr = $.ajax({
type: "POST",
url: url,
data: postdata,
dataType: 'json',
cache: false,
async: false
});
// 'async' has to be 'false' for this to work
var response = {valid: jqxhr.statusText, data: jqxhr.responseJSON};
return response;
}
Zauważ, że powyższy kod działa tylko w przypadek, w którym async jest false . Jeśli ustawisz async: true zwracany obiekt jqxhrnie będzie ważny w momencie, gdy wywołanie AJAX zostanie zwrócone, dopiero później, gdy wywołanie asynchroniczne zostanie zakończone, ale jest to o wiele za późno, aby ustawić zmienną response.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-30 21:25:39
Z async: false
dostajesz zablokowaną przeglądarkę.
Dla nieblokującego rozwiązania synchronicznego można użyć następującego:
ES6 / ECMAScript2015
Z ES6 możesz użyć generatora i biblioteki co :
beforecreate: function (node, targetNode, type, to) {
co(function*(){
let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
});
}
ES7
Z ES7 możesz po prostu użyć asyc:
beforecreate: function (node, targetNode, type, to) {
(async function(){
let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
//Just use the result here
})();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-20 19:52:07
Oto przykład:
$.ajax({
url: "test.html",
async: false
}).done(function(data) {
// Todo something..
}).fail(function(xhr) {
// Todo something..
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-16 13:20:10
Po pierwsze powinniśmy zrozumieć kiedy używamy $.ajax i kiedy używamy $.get/$.post
Gdy wymagamy niskiego poziomu kontroli nad żądaniem ajax, takim jak ustawienia nagłówka żądania, ustawienia buforowania, ustawienia synchroniczne itp.więc powinniśmy iść za $.ajax.
$.get/$.post: gdy nie wymagamy niskiego poziomu kontroli nad żądaniem ajax.Tylko proste get/post danych do serwera.jest skrótem
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
I dlatego nie możemy korzystać z innych funkcji (synchronizacja, cache itd.) z $.get/$.poczta.
Stąd do kontroli niskiego poziomu (synchronizacja, pamięć podręczna itp.) nad żądaniem ajax, powinniśmy przejść do $.ajax
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-03 09:52:59
To jest moja prosta implementacja dla żądań asynchronicznych z jQuery. Mam nadzieję, że to komuś pomoże.
var queueUrlsForRemove = [
'http://dev-myurl.com/image/1',
'http://dev-myurl.com/image/2',
'http://dev-myurl.com/image/3',
];
var queueImagesDelete = function(){
deleteImage( queueUrlsForRemove.splice(0,1), function(){
if (queueUrlsForRemove.length > 0) {
queueImagesDelete();
}
});
}
var deleteImage = function(url, callback) {
$.ajax({
url: url,
method: 'DELETE'
}).done(function(response){
typeof(callback) == 'function' ? callback(response) : null;
});
}
queueImagesDelete();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-15 19:55:31
Ponieważ XMLHttpReponse
synchroniczne działanie jest przestarzałe, wymyśliłem następujące rozwiązanie, które zawija XMLHttpRequest
. Pozwala to na uporządkowanie zapytań AJAX, a jednocześnie ma charakter asycnronous, co jest bardzo przydatne w przypadku jednorazowych tokenów CSRF.
Jest również przezroczysty, więc biblioteki takie jak jQuery będą działać bezproblemowo.
/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
var xhr = new _XMLHttpRequest();
var _send = xhr.send;
xhr.send = function()
{
/* queue the request, and if it's the first, process it */
XHRQueue.push([this, arguments]);
if (XHRQueue.length == 1)
this.processQueue();
};
xhr.processQueue = function()
{
var call = XHRQueue[0];
var xhr = call[0];
var args = call[1];
/* you could also set a CSRF token header here */
/* send the request */
_send.apply(xhr, args);
};
xhr.addEventListener('load', function(e)
{
/* you could also retrieve a CSRF token header here */
/* remove the completed request and if there is more, trigger the next */
XHRQueue.shift();
if (XHRQueue.length)
this.processQueue();
});
return xhr;
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-29 13:30:01