Есть ли причина использовать синхронный запрос XMLHttpRequest? - PullRequest
85 голосов
/ 18 января 2010

Кажется, что большинство делает асинхронные запросы с XMLHttpRequest, но, очевидно, тот факт, что существует возможность делать синхронные запросы, указывает на то, что для этого может быть веская причина.Так какой же может быть эта веская причина?

Ответы [ 18 ]

29 голосов
/ 04 августа 2011

Синхронные XHR полезны для сохранения пользовательских данных.Если вы обрабатываете событие beforeunload, вы можете выгружать данные на сервер, когда пользователь закрывает страницу.

Если это было сделано с использованием параметра асинхронности, страница может закрыться до завершения запроса.Выполнение этого синхронно гарантирует, что запрос завершится или завершится с ошибкой ожидаемым образом.

26 голосов
/ 18 января 2010

Я думаю, что они могут стать более популярными по мере развития стандартов HTML 5. Если веб-приложение получит доступ к веб-работникам, я мог бы предвидеть, что разработчики используют выделенного веб-работника для синхронных запросов, как сказал Джонатан, для обеспечения того, чтобы один запрос выполнялся раньше другого. В текущей ситуации с одним потоком это не совсем идеальный дизайн, поскольку он блокируется до тех пор, пока запрос не будет выполнен.

13 голосов
/ 30 июня 2010

Обновление:

Ниже приведено указание - но безуспешно при доставке - что с появлением лучшей асинхронной обработки запросов, на самом деле нет причин использовать синхронные запросы, если только мы не намерены намеренно блокировать действия пользователей, пока запрос не будет завершен - звучит злобно :)

Несмотря на то, что это может звучать плохо, могут быть случаи, когда важно, чтобы запрос (или серия запросов) выполнялся до того, как пользователь покидает страницу, или до того, как будет выполнено действие - блокирование выполнения другого кода (например, предотвращение возврата кнопка) может уменьшить количество ошибок / обслуживания для плохо системы; Тем не менее, я никогда не видел его в дикий и подчеркиваю, что этого следует избегать.

Библиотеки, такие как обещают , симулируют синхронность, связывая процессы с помощью обратных вызовов. Это удовлетворяет большинству потребностей разработки, когда требуется заказывать неблокирующие события, которые позволяют браузерам сохранять отзывчивость для пользователя (хороший UX).

Как указано в документации Mozilla , существуют случаи, когда вам приходится использовать синхронные запросы; тем не менее, также указан обходной путь, который использует маяк (недоступный в IE / Safari) для таких случаев. Несмотря на то, что это экспериментально, если оно когда-либо достигнет принятия стандартов, оно, возможно, может вбить гвоздь в гроб с синхронными запросами.


Вы хотели бы выполнять синхронные вызовы при любой обработке, подобной транзакции, или там, где необходим какой-либо порядок операций.

Например, допустим, вы хотите настроить событие для выхода из системы после воспроизведения песни. Если сначала происходит выход из системы, то песня никогда не будет воспроизводиться. Это требует синхронизации запросов.

Другой причиной может быть работа с WebService, особенно при выполнении математических операций на сервере.

Пример: На сервере есть переменная со значением 1.

 Step (1) Perform Update: add 1 to variable
 Step (2) Perform Update: set variable to the power of 3
 End Value: variable equals 8

Если шаг (2) выполняется первым, то конечное значение равно 2, а не 8; таким образом, порядок работы имеет значение и необходима синхронизация.


Очень мало раз, когда синхронный вызов может быть оправдан в обычном примере из реального мира. Возможно, когда вы нажимаете кнопку «Войти», а затем нажимаете на часть сайта, требующую входа пользователя в систему.

Как уже говорили другие, он свяжет ваш браузер, поэтому держитесь подальше от него, где сможете.

Однако вместо синхронных вызовов часто пользователи хотят остановить событие, которое загружается в данный момент, а затем выполнить какую-либо другую операцию. В некотором смысле это синхронизация, поскольку первое событие завершается до начала второго. Для этого используйте метод abort () объекта подключения xml.

8 голосов
/ 18 января 2010

Я бы сказал, что если вы решите заблокировать браузер пользователя, когда запрос будет завершен, тогда обязательно используйте синхронный запрос.

Если ваша цель - сериализация запросов, то это можно сделать с помощью асинхронных запросов, с помощью обратного вызова onComplete вашего предыдущего запроса, запускающего следующую строку.

6 голосов
/ 23 июля 2010

Я вижу использование синхронных запросов XHR, которые должны использоваться, когда ресурс в переменной области должен быть загружен до того, как другие статические ресурсы на странице, которые зависят от первого ресурса, будут полностью функционировать. Фактически, я реализую такой запрос XHR в своем небольшом подпроекте, тогда как ресурсы JavaScript находятся в разных местах на сервере в зависимости от набора конкретных параметров. Последующие ресурсы JavaScript полагаются на эти переменные ресурсы, и такие файлы ДОЛЖНЫ гарантированно загружаться до загрузки других зависимых файлов, что делает приложение целостным.

Эта основа идеи действительно расширяет ответ vol7ron. Процедуры на основе транзакций - действительно единственное время, когда должны выполняться синхронные запросы. В большинстве других случаев асинхронные вызовы являются лучшей альтернативой, в которой после вызова DOM обновляется по мере необходимости. Во многих случаях, например в пользовательских системах, некоторые функции могут быть заблокированы «неавторизованными пользователями» до тех пор, пока они не войдут в систему как таковые. Эти функции после асинхронного вызова разблокируются с помощью процедуры обновления DOM.

Я бы, наконец, должен сказать, что согласен с мнением большинства людей по этому вопросу: везде, где это возможно, следует избегать синхронных запросов XHR, так как при работе он блокирует синхронные вызовы. При реализации синхронных запросов они должны выполняться так, чтобы браузер обычно блокировался, в любом случае, скажем, в разделе HEAD до того, как загрузка страницы действительно произошла.

5 голосов
/ 02 апреля 2015

Существует множество случаев, когда блокирование пользовательского интерфейса является именно желаемым поведением.

Возьмите приложение с несколькими полями, и некоторые поля должны быть проверены с помощью вызова xmlhttp на удаленном сервере, предоставив в качестве входных данных значение этого поля и значения других полей.

В синхронном режиме логика проста, блокировка, с которой сталкивается пользователь, очень короткая и проблем нет.

В асинхронном режиме пользователь может изменять значения любых других полей во время проверки исходного поля. Эти изменения будут запускать другие вызовы xmlhttp со значениями из исходного поля, которые еще не проверены. Что произойдет, если первоначальная проверка не удалась? Чистый беспорядок. Если режим синхронизации становится устаревшим и запрещенным, логика приложения становится кошмаром. По сути, приложение должно быть переписано для управления блокировками (например, отключение других элементов во время процессов проверки). Сложность кода значительно возрастает. Невыполнение этого требования может привести к сбою логики и, в конечном итоге, к повреждению данных.

По сути, вопрос заключается в следующем: что важнее, неблокированный пользовательский интерфейс или риск повреждения данных? Ответ должен остаться у разработчика приложения, а не у W3C.

4 голосов
/ 10 декабря 2011

jQuery использует синхронный AJAX для внутренних целей при некоторых обстоятельствах.При вставке HTML, который содержит скрипты, браузер не будет их выполнять.Сценарии должны быть выполнены вручную.Эти скрипты могут прикреплять обработчики кликов.Предположим, пользователь щелкает элемент до того, как обработчик присоединен, и страница не будет функционировать, как предполагалось.Поэтому, чтобы предотвратить условия гонки, синхронный AJAX будет использоваться для получения этих сценариев.Поскольку синхронный AJAX эффективно блокирует все остальное, можно быть уверенным, что сценарии и события выполняются в правильном порядке.

3 голосов
/ 25 декабря 2015

С 2015 года настольные приложения javascript становятся все более популярными. Обычно в этих приложениях при загрузке локальных файлов (и загрузка их с использованием XHR является совершенно допустимым вариантом) скорость загрузки настолько высока, что нет особого смысла усложнять код с помощью асинхронного кода. Конечно, могут быть случаи, когда асинхронность - это путь (запрос контента из Интернета, загрузка действительно больших файлов или огромного количества файлов в одном пакете), но в остальном синхронизация работает просто отлично (и намного проще в использовании) .

2 голосов
/ 24 июля 2015

SYNC vs ASYNC: В чем разница?

В основном это сводится к следующему:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
});
console.info('Goodbye cruel world!');

Когда doSomething равно синхронно , это выдает:

Hello, World!
Got result!
Goodbye cruel world!

В отличие от этого, если doSomething равен асинхронным , это выдает:

Hello, World!
Goodbye cruel world!
Got result!

Поскольку функция doSomething выполняет свою работу асинхронно, она возвращается до завершения своей работы. Таким образом, мы получаем результат только после печати Goodbye cruel world!

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

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
    if (result === 'good') {
        console.info('I feel great!');
    }
    else {
        console.info('Goodbye cruel world!');
    }
});

Таким образом, только тот факт, что для того, чтобы происходили две или три вещи, должно происходить синхронно (хотя для большинства людей синхронизировать код проще).

ПОЧЕМУ ИСПОЛЬЗОВАТЬ СИНХРОННЫЙ XMLHTTPREQUEST?

В некоторых ситуациях вам нужен результат до завершения вызываемой функции. Рассмотрим этот сценарий:

function lives(name) {
    return (name !== 'Elvis');
}
console.info('Elvis ' + (lives('Elvis') ? 'lives!' : 'has left the building...');

Предположим, у нас нет контроля над вызывающим кодом (строка console.info), и нам нужно изменить функцию lives, чтобы запросить сервер ... Мы не можем выполнить асинхронный запрос к серверу изнутри lives и до сих пор имеем наш ответ до завершения lives. Поэтому мы не будем знать, возвращать ли true или false. Единственный способ получить результат до завершения функции - выполнить синхронный запрос.

Как Sami Samhuri упоминает в своем ответе, очень реальным сценарием, в котором вам может потребоваться ответ на запрос к серверу до завершения функции, является событие onbeforeunload, так как это последняя функция из вашего приложения, которая когда-либо выполнялась раньше окно закрывается.

Мне НЕ ТРЕБУЕТСЯ ВЫЗОВ СИНХРОНИЗАЦИИ, НО Я ИСПОЛЬЗУЮ ИХ В КАКОЙ-ЛИБО РАЗ, КАК ОНИ ЛЕГКО

Пожалуйста, не надо. Синхронные звонки блокируют ваш браузер, и приложение перестает отвечать на запросы. Но ты прав. Асинхронный код сложнее. Однако есть способ сделать это гораздо проще. Не так просто, как синхронизировать код, но он приближается: Обещание с.

Вот пример: два асинхронных вызова должны успешно завершиться, прежде чем может быть запущен третий сегмент кода:

var carRented = rentCar().then(function(car){
  gasStation.refuel(car);
});

var hotelBooked = bookHotel().then(function(reservation) {
  reservation.confirm();
});

Promise.all([carRented, hotelBooked]).then(function(){
  // At this point our car is rented and our hotel booked.
  goOnHoliday();
});

Вот как бы вы реализовали bookHotel:

function bookHotel() {
  return new Promise(function(resolve, reject){
    if (roomsAvailable()) {
      var reservation = reserveRoom();
      resolve(reservation);
    }
    else {
      reject(new Error('Could not book a reservation. No rooms available.'));
    }
  });
}

См. Также: Пишите лучше JavaScript с обещаниями .

2 голосов
/ 24 декабря 2013

Причина:

Допустим, у вас есть приложение ajax, которое должно выполнить полдюжины http, чтобы загрузить различные данные с сервера, прежде чем пользователь сможет что-либо сделать.

Очевидно, вы хотите, чтобы это срабатывало при загрузке.

Синхронные вызовы работают очень хорошо для этого без какой-либо дополнительной сложности в коде. Это просто и понятно.

Минус:

Единственным недостатком является то, что ваш браузер блокируется до тех пор, пока не будут загружены все данные или не истечет время ожидания. Что касается рассматриваемого приложения ajax, это не представляет большой проблемы, поскольку приложение бесполезно, пока все исходные данные не будут загружены.

Альтернативный

Однако многие браузеры блокируют все окна / вкладки, когда javascript занят в любом из них, что является глупой проблемой дизайна браузера - но в результате блокировка на возможно медленных сетевых подключениях не вежлива, если не позволяет пользователям использование других вкладок в ожидании загрузки страницы ajax.

Однако похоже, что синхронные операции были удалены или ограничены в последних браузерах. Я не уверен, что это потому, что кто-то решил, что они всегда были плохими, или авторы браузера были смущены рабочим проектом WC по этой теме.

http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method выглядит так (см. Раздел 4.7.3), что вы не можете устанавливать тайм-аут при использовании режима блокировки. Мне кажется, это кажется интуитивно понятным: всякий раз, когда кто-то блокирует ввод-вывод, вежливо установить разумное время ожидания, так зачем разрешать блокировку ввода-вывода, но не с указанным пользователем временем ожидания?

Мое мнение таково, что блокировка ввода-вывода играет жизненно важную роль в некоторых ситуациях, но должна выполняться правильно. Хотя одной вкладке или окну браузера нельзя заблокировать все остальные вкладки или окна, это недостаток дизайна браузера. Стыд, где стыд. Но в некоторых случаях вполне допустимо, чтобы отдельные вкладки или окна не реагировали в течение нескольких секунд (например, с помощью блокирования ввода-вывода / HTTP GET) в некоторых ситуациях - например, при загрузке страницы, возможно, большого количества данных. должно быть, прежде чем что-либо может быть сделано в любом случае. Иногда правильно реализованный код блокировки - самый чистый способ сделать это.

Конечно, эквивалентную функцию в этом случае можно получить с помощью асинхронного http, но какой тип глупой процедуры требуется?

Полагаю, я бы попробовал что-то вроде этого:

При загрузке документа выполните следующие действия: 1: установить 6 глобальных переменных флага «Done», инициализированных в 0. 2: Выполнить все 6 фоновых операций (при условии, что порядок не имеет значения)

Затем обратные вызовы завершения для каждого из 6 http get установят соответствующие флаги «Готово». Кроме того, каждый обратный вызов будет проверять все остальные флаги готовности, чтобы увидеть, завершены ли все 6 HTTP-запросов. Последний обратный вызов для завершения, увидев, что все остальные завершили, затем вызовет РЕАЛЬНУЮ функцию инициализации, которая затем настроит все, теперь, когда все данные получены.

Если порядок выборки имел значение - или если веб-сервер не смог принять несколько запросов одновременно - тогда вам понадобится что-то вроде этого:

В onload () будет запущен первый http get. В обратном вызове будет запущен второй. Это обратный вызов, третий - и так далее, и так далее, при каждом обратном вызове запускается следующий HTTP GET. Когда последний вернулся, он вызвал бы настоящую подпрограмму init ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...