У меня есть виджет JavaScript, который предоставляет стандартные точки расширения. Одна из них - функция beforecreate. Он должен вернуть false, чтобы предотвратить создание элемента.
Я добавил в эту функцию вызов Ajax с помощью 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);
});
}
Но я хочу, чтобы мой виджет не создавал элемент, поэтому я должен возвращать false в материнской функции, а не в обратном вызове. Есть ли способ выполнить синхронный запрос AJAX с помощью jQuery или любого другого API в браузере?
Предлагаю функцию Саяка. У нас есть буква Т? Да, ванна, дай мне 3 Т.
@Kos на высоте. Синхронизация XHR здесь не требуется
Если люди просят у меня одного совета при запуске javascript, я говорю: примите асинхронный характер javascript, не пытайтесь бороться с этим.
Вы можете попробовать использовать embeddedjs.com
Этот вопрос похож на вопрос «как мне сохранить свои пароли пользователей в виде обычного текста?» Конечно, есть ответ, но не делайте этого.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Из документация jQuery: вы указываете для параметра асинхронный значение ложный, чтобы получить синхронный запрос Ajax. Затем ваш обратный вызов может установить некоторые данные до продолжения вашей материнской функции.
Вот как будет выглядеть ваш код, если его изменить, как предлагается:
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
});
}
Собственно, нельзя использовать get (), post (), load () для синхронных вызовов. Только у ajax () есть параметр «async», которому можно присвоить значение «false».
@ SLA80 Нет. Начиная с jQuery 1.1: stackoverflow.com/questions/6849686/…
@StuperUser: ответ по-прежнему правильный и актуален, если вы хотите, чтобы только определенные запросы были синхронными.
@qualidafial мой комментарий направлен на неправильный комментарий SLA80; можно использовать get (), post (), load () для синхронных вызовов.
просто примечание, добавление async:false отлично работает для меня, пока я устанавливаю всю функцию ajax как значение некоторой переменной. например var ajaxresults = $.ajax({....
async false больше не поддерживается для jQuery> = 1.8. Обратитесь к api.jquery.com/jQuery.ajax
@ken async: false по-прежнему поддерживается в jQuery> = 1.8. Возможность использовать async: false с jqXHR ($.Deferred) устарела. Другими словами, необходимо использовать более новые варианты обратного вызова успеха / ошибки / завершения вместо устаревших методов, например jqXHR.done().
Безопасно ли использовать Async:False, потому что он будет удерживать выполнение остального кода. Как только вы получите ответ ajax, только тогда будет выполнен остальной код. Что делать, если сервер не отвечает на запрос Ajax? следует ли добавить тайм-аут для продолжения другого запроса, если сервер не отвечает на запрос Ajax?
async устарел
@Ikbel: нет, см. Комментарий Бена Джонсона. Он устарел вместе с $.Deferred, а не сам по себе.
Важно отметить, что опция async: false устарела для новых версий jQuery> 3.0. Таким образом, этот метод не реализуем.
@bis Неправда. Что касается этого комментария, официальные документы по-прежнему не считает его устаревшим и работает без предупреждения. См. эта рабочий пример
@JohnNeuhaus, ноябрь 2020 г .: JQuery показывает предупреждение в консоли. async: false больше не подходит.
Отличное решение! Когда я пытался реализовать это, я заметил, что если я возвращал значение в условии успеха, оно возвращалось как undefined. Мне пришлось сохранить его в переменной и вернуть эту переменную. Это метод, который я придумал:
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;
}
Это потому, что вы возвращали значение из обратного вызова, а не из getWhatever. Таким образом, вы вернули ничего такого, то есть undefined из вашего getWhatever.
это абсолютно неправильно. Вы не можете быть уверены, что асинхронный вызов завершился при возврате strReturn.
Это синхронный вызов (async: false).
Вы можете перевести настройку jQuery Ajax в синхронный режим, вызвав
jQuery.ajaxSetup({async:false});
А затем выполните свои вызовы Ajax с помощью jQuery.get( ... );
Тогда просто включи его еще раз
jQuery.ajaxSetup({async:true});
Я предполагаю, что это работает так же, как предлагает @Adam, но это может быть полезно для тех, кто действительно хочет перенастроить свой jQuery.get() или jQuery.post() на более сложный синтаксис jQuery.ajax().
Это действительно плохая идея, зачем вам устанавливать ее на глобальном уровне? А потом принудительно сбросить его после?
По крайней мере, это лучшая плохая идея. вместо того, чтобы сказать: «НИКАКОГО НЕТ, КРОМЕ $.ajax()». ;)
function getURL(url){
return $.ajax({
type: "GET",
url: url,
cache: false,
async: false
}).responseText;
}
//example use
var msg=getURL("message.php");
alert(msg);
Обратите внимание, что вы можете получить следующее: «Синхронный XMLHttpRequest в основном потоке устарел из-за его пагубного воздействия на взаимодействие с конечным пользователем».
@Hari Как можно выполнять синхронный вызов ajax с помощью jQuery без использования основного потока?
Я не вижу, что в этом ответе есть что предложить, это просто принятый ответ, завернутый в функцию, на который ответил четыре года спустя. Советовать людям использовать C + P - плохо, потому что функция не указывает, что она делает. «Итак, getURL против get? Почему один мой браузер зависает?» и т.п.
Все эти ответы упускают из виду, что выполнение вызова Ajax с async: false приведет к зависанию браузера до завершения запроса Ajax. Использование библиотеки управления потоком решит эту проблему без зависания браузера. Вот пример с 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();
}
Синхронные вызовы удобны, если вы хотите собрать быстрый тестовый набор для серверной части REST и предпочитаете простоту аду обратных вызовов.
Это пример:
$.ajax({
url: "test.html",
async: false
}).done(function(data) {
// Todo something..
}).fail(function(xhr) {
// Todo something..
});
В чем смысл использования async false с решением, основанным на обещаниях. Это только блокирует браузер без всякой пользы.
@GoneCoding есть ситуации, когда нужно выполнить код в точной последовательности, в этой ситуации мы можем использовать async false
@Nikki: Это абсолютно нет способ запускать их последовательно. Используйте асинхронные обещания (которые ajax уже вызывает return) и .then() или done() (как это уже показано). Блокировка браузера - очень плохой пользовательский опыт. Как я уже сказал, использование async: false в этом примере - пустая трата времени.
Я использовал ответ, данный Carcione, и изменил его, чтобы использовать 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');
}
}
Я добавил тип данных из 'JSON' и изменил .responseText на responseJSON.
Я также получил статус, используя свойство statusText возвращенного объекта. Обратите внимание, что это статус ответа Ajax, а не то, действителен ли JSON.
Серверная часть должна возвращать ответ в правильном (правильно сформированном) JSON, иначе возвращаемый объект будет неопределенным.
При ответе на исходный вопрос необходимо учитывать два аспекта. Один сообщает Ajax работать синхронно (путем установки асинхронный: ложь), а другой возвращает ответ через оператор return вызывающей функции, а не через функцию обратного вызова.
Я также попробовал это с помощью POST, и это сработало.
Я изменил GET на POST и добавил данные: 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;
}
Обратите внимание, что приведенный выше код работает только в том случае, если асинхронный равно ложный. Если бы вы установили асинхронный: правда, возвращаемый объект jqxhr был бы недействителен в момент возврата вызова AJAX, только позже, когда асинхронный вызов завершится, но уже слишком поздно для установки переменной отклик.
Имейте в виду, что если вы выполняете междоменный вызов Ajax (используя JSONP) - вы не могу делаете это синхронно, флаг async будет игнорироваться jQuery.
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
Для JSONP-вызовов вы можете использовать:
С async: false вы получаете заблокированный браузер.
Для неблокирующего синхронного решения вы можете использовать следующее:
С ES6 вы можете использовать генератор и совместная библиотека:
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 вы можете просто использовать asyc await:
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
})();
}
Обратите внимание, что вы можете просто передать async function до создания beforecreate: async function(.... и удалить самозапускаемую асинхронную функцию.
Примечание: вы не должны использовать async: false из-за следующих предупреждающих сообщений:
Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.
Хром даже предупреждает об этом в консоли:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
Это может сломать вашу страницу, если вы будете делать что-то подобное, поскольку она может перестать работать в любой день.
Если вы хотите сделать это так, что все еще кажется, что он синхронный, но все еще не блокируется, вам следует использовать async / await и, возможно, также некоторый ajax, который основан на обещаниях, таких как новый Принести API
async function foo() {
var res = await fetch(url)
console.info(res.ok)
var json = await res.json()
console.info(json)
}
Редактировать Chrome работает с Запрещение синхронизации XHR при закрытии страницы, когда страница перемещается или закрывается пользователем. Это включает в себя перед выгрузкой, выгрузкой, скрытием страницы и изменением видимости.
если это ваш вариант использования, вы можете вместо этого взглянуть на navigator.sendBeacon
Страница также может отключить запрос синхронизации либо с заголовками http, либо с атрибутом allow iframe.
Обратите внимание, что вы должны заключить вызов await fetch(url) в блок try... catch, чтобы перехватить любые асинхронные ошибки.
функция foo была преобразована в обещание, просто используя слово async в начале, поэтому вы можете просто выполнить foo().catch(...), чтобы поймать его
Chrome уже запретил асинхронный ajax на странице beforeunload, но затем отменил изменение после отрицательной обратной связи bugs.chromium.org/p/chromium/issues/detail?id=952452
Во-первых, мы должны понимать, когда мы используем $ .ajax, а когда мы используем $ .get / $. Post.
Когда нам требуется низкоуровневый контроль над запросом ajax, такой как настройки заголовка запроса, настройки кеширования, синхронные настройки и т. д., Тогда мы должны использовать $ .ajax.
$ .get / $. post: когда нам не нужен низкоуровневый контроль над запросом ajax. Достаточно просто получить / отправить данные на сервер. Это сокращение от
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
и, следовательно, мы не можем использовать другие функции (синхронизацию, кеширование и т. д.) с $ .get / $. post.
Следовательно, для низкоуровневого управления (синхронизация, кеширование и т. д.) Над запросом ajax мы должны использовать $ .ajax
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
это моя простая реализация для запросов ASYNC с jQuery. Надеюсь, это кому-нибудь поможет.
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();
Поскольку синхронная работа XMLHttpReponse устарела, я предложил следующее решение, которое включает XMLHttpRequest. Это позволяет упорядочивать запросы AJAX, оставаясь при этом асинхронными по своей природе, что очень полезно для одноразовых токенов CSRF.
Он также прозрачен, поэтому библиотеки, такие как jQuery, будут работать без проблем.
/* 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;
};
Поскольку исходный вопрос касался jQuery.get, здесь стоит упомянуть, что (как упоминалось здесь) один мог использует async: false в $.get(), но в идеале избегать использует его, поскольку асинхронный XMLHTTPRequest устарел (и браузер может выдать предупреждение):
$.get({
url: url,// mandatory
data: data,
success: success,
dataType: dataType,
async:false // to make it synchronous
});
Правильный способ решить эту проблему - переписать обещания использования точки расширения вашего виджета. Этот способ легко позволит вам настроить асинхронное действие (например, запрос ajax) как
beforecreate.