Как я могу заставить jQuery выполнять синхронный, а не асинхронный запрос Ajax?

У меня есть виджет 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 в браузере?

Правильный способ решить эту проблему - переписать обещания использования точки расширения вашего виджета. Этот способ легко позволит вам настроить асинхронное действие (например, запрос ajax) как beforecreate.

Kos 22.12.2013 15:32

Предлагаю функцию Саяка. У нас есть буква Т? Да, ванна, дай мне 3 Т.

Cody O'Dell 14.04.2016 03:18

@Kos на высоте. Синхронизация XHR здесь не требуется

Michael Westcott 09.10.2016 13:47

Если люди просят у меня одного совета при запуске javascript, я говорю: примите асинхронный характер javascript, не пытайтесь бороться с этим.

Emmanuel Delay 14.12.2017 14:55

Вы можете попробовать использовать embeddedjs.com

firstpostcommenter 07.08.2018 17:48

Этот вопрос похож на вопрос «как мне сохранить свои пароли пользователей в виде обычного текста?» Конечно, есть ответ, но не делайте этого.

Vectorjohn 30.10.2018 02:04
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1 249
6
752 068
14
Перейти к ответу Данный вопрос помечен как решенный

Ответы 14

Ответ принят как подходящий

Из документация 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 16.05.2010 15:41

@ SLA80 Нет. Начиная с jQuery 1.1: stackoverflow.com/questions/6849686/…

StuperUser 01.08.2011 21:45

@StuperUser: ответ по-прежнему правильный и актуален, если вы хотите, чтобы только определенные запросы были синхронными.

qualidafial 08.03.2012 21:58

@qualidafial мой комментарий направлен на неправильный комментарий SLA80; можно использовать get (), post (), load () для синхронных вызовов.

StuperUser 08.03.2012 22:00

просто примечание, добавление async:false отлично работает для меня, пока я устанавливаю всю функцию ajax как значение некоторой переменной. например var ajaxresults = $.ajax({....

d-_-b 16.02.2013 03:07

async false больше не поддерживается для jQuery> = 1.8. Обратитесь к api.jquery.com/jQuery.ajax

ken 05.08.2015 11:43

@ken async: false по-прежнему поддерживается в jQuery> = 1.8. Возможность использовать async: false с jqXHR ($.Deferred) устарела. Другими словами, необходимо использовать более новые варианты обратного вызова успеха / ошибки / завершения вместо устаревших методов, например jqXHR.done().

Ben Johnson 30.10.2015 17:09

Безопасно ли использовать Async:False, потому что он будет удерживать выполнение остального кода. Как только вы получите ответ ajax, только тогда будет выполнен остальной код. Что делать, если сервер не отвечает на запрос Ajax? следует ли добавить тайм-аут для продолжения другого запроса, если сервер не отвечает на запрос Ajax?

Swap-IOS-Android 16.08.2017 10:34

async устарел

Ikbel 14.09.2017 20:47

@Ikbel: нет, см. Комментарий Бена Джонсона. Он устарел вместе с $.Deferred, а не сам по себе.

thomasb 16.11.2017 16:10

Важно отметить, что опция async: false устарела для новых версий jQuery> 3.0. Таким образом, этот метод не реализуем.

bishal 07.03.2018 09:02

@bis Неправда. Что касается этого комментария, официальные документы по-прежнему не считает его устаревшим и работает без предупреждения. См. эта рабочий пример

John Neuhaus 29.06.2018 22:16

@JohnNeuhaus, ноябрь 2020 г .: JQuery показывает предупреждение в консоли. async: false больше не подходит.

Peter VARGA 16.11.2020 13:56

Отличное решение! Когда я пытался реализовать это, я заметил, что если я возвращал значение в условии успеха, оно возвращалось как 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.

Lightness Races in Orbit 12.07.2011 03:35

это абсолютно неправильно. Вы не можете быть уверены, что асинхронный вызов завершился при возврате strReturn.

Thomas Fritz 22.02.2012 15:30

Это синхронный вызов (async: false).

James in Indy 05.03.2012 22:13

Вы можете перевести настройку jQuery Ajax в синхронный режим, вызвав

jQuery.ajaxSetup({async:false});

А затем выполните свои вызовы Ajax с помощью jQuery.get( ... );

Тогда просто включи его еще раз

jQuery.ajaxSetup({async:true});

Я предполагаю, что это работает так же, как предлагает @Adam, но это может быть полезно для тех, кто действительно хочет перенастроить свой jQuery.get() или jQuery.post() на более сложный синтаксис jQuery.ajax().

Это действительно плохая идея, зачем вам устанавливать ее на глобальном уровне? А потом принудительно сбросить его после?

Juan Mendes 04.08.2014 22:16

По крайней мере, это лучшая плохая идея. вместо того, чтобы сказать: «НИКАКОГО НЕТ, КРОМЕ $.ajax()». ;)

Rzassar 31.05.2016 06:22

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 07.05.2015 23:09

@Hari Как можно выполнять синхронный вызов ajax с помощью jQuery без использования основного потока?

Jose Nobile 10.02.2016 00:29

Я не вижу, что в этом ответе есть что предложить, это просто принятый ответ, завернутый в функцию, на который ответил четыре года спустя. Советовать людям использовать C + P - плохо, потому что функция не указывает, что она делает. «Итак, getURL против get? Почему один мой браузер зависает?» и т.п.

moopet 26.10.2016 13:13

Все эти ответы упускают из виду, что выполнение вызова 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 и предпочитаете простоту аду обратных вызовов.

Distortum 19.05.2014 06:08

Это пример:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

В чем смысл использования async false с решением, основанным на обещаниях. Это только блокирует браузер без всякой пользы.

Gone Coding 05.09.2017 21:22

@GoneCoding есть ситуации, когда нужно выполнить код в точной последовательности, в этой ситуации мы можем использовать async false

Nikki 06.10.2017 15:05

@Nikki: Это абсолютно нет способ запускать их последовательно. Используйте асинхронные обещания (которые ajax уже вызывает return) и .then() или done() (как это уже показано). Блокировка браузера - очень плохой пользовательский опыт. Как я уже сказал, использование async: false в этом примере - пустая трата времени.

Gone Coding 07.10.2017 00:38

Я использовал ответ, данный 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-вызовов вы можете использовать:

  1. Ajax-вызов к вашему собственному домену - и выполнение междоменного вызова на стороне сервера
  2. Измените свой код, чтобы он работал асинхронно
  3. Используйте библиотеку «секвенсора функций», например Frame.js (это отвечать)
  4. Блокировать пользовательский интерфейс вместо блокировки выполнения (это отвечать) (мой любимый способ)

С async: false вы получаете заблокированный браузер. Для неблокирующего синхронного решения вы можете использовать следующее:

ES6 / ECMAScript2015

С 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

С 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(.... и удалить самозапускаемую асинхронную функцию.

Daniel Krom 07.05.2018 19:05

Примечание: вы не должны использовать 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, чтобы перехватить любые асинхронные ошибки.

inostia 20.04.2017 00:39

функция foo была преобразована в обещание, просто используя слово async в начале, поэтому вы можете просто выполнить foo().catch(...), чтобы поймать его

Endless 20.04.2017 11:47

Chrome уже запретил асинхронный ajax на странице beforeunload, но затем отменил изменение после отрицательной обратной связи bugs.chromium.org/p/chromium/issues/detail?id=952452

Alex 20.06.2019 13:45

Во-первых, мы должны понимать, когда мы используем $ .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
});

Другие вопросы по теме