Есть ли причина использовать синхронный XMLHttpRequest?
Кажется, что большинство из них выполняют асинхронные запросы с XMLHttpRequest, но, очевидно, тот факт, что есть возможность выполнять синхронные запросы, указывает, что для этого может быть веская причина. Итак, какова может быть эта веская причина?
Ответы
Ответ 1
Я думаю, что они могут стать более популярными по мере продвижения стандартов HTML 5. Если веб-приложение получает доступ к веб-работникам, я мог бы предусмотреть разработчиков, использующих выделенного веб-рабочего, для выполнения синхронных запросов, как сказал Джонатан, чтобы гарантировать, что один запрос произойдет раньше другого. В текущей ситуации одного потока это менее идеальный дизайн, поскольку он блокируется до тех пор, пока запрос не будет завершен.
Ответ 2
Синхронные XHR полезны для сохранения пользовательских данных. Если вы обрабатываете событие beforeunload
, вы можете загружать данные на сервер, когда пользователь закрывает страницу.
Если это было сделано с использованием параметра async, страница может закрыться до завершения запроса. Выполнение этого синхронно гарантирует, что запрос завершится или завершится неудачно.
Ответ 3
Обновление:
Ниже было намечено - но не удалось доставить - что с появлением лучшей асинхронной обработки запросов действительно нет причин использовать синхронные запросы, если намеревается намеренно заблокировать пользователей от каких-либо действий до тех пор, пока запрос не будет завершен - звучит злонамеренно:)
Хотя это может показаться плохим, могут быть моменты, когда важно, чтобы запрос (или серия запросов) возникал до того, как пользователь покинул страницу или до того, как действие было выполнено - блокирование другого выполнения кода (например, предотвращение возврата ) может привести к уменьшению ошибок/обслуживания плохо разработанной системы; что я никогда не видел его в дикой природе и подчеркивал, что его следует избегать.
Библиотеки, такие как promise, симулируют синхронизацию посредством цепочки процессов через обратные вызовы. Это соответствует большинству потребностей в области развития, когда желание состоит в том, чтобы иметь упорядоченные, неблокирующие события, которые позволяют браузерам сохранять отзывчивость для пользователя (хороший 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.
Ответ 4
Я бы сказал, что если вы считаете, что блокировка браузера пользователя в то время, когда запрос завершен, то обязательно используйте синхронный запрос.
Если сериализация запросов является вашей целью, тогда это может быть выполнено с использованием асинхронных запросов, поскольку обратный вызов onComplete вашего предыдущего запроса загорается следующим образом.
Ответ 5
Я могу видеть использование синхронных запросов XHR, которые будут использоваться, когда ресурс в местоположении переменной должен быть загружен до того, как другие статические ресурсы на странице, которые зависят от первого ресурса, будут полностью функционировать. На самом деле, я выполняю такой запрос XHR в небольшом суб-проекте, тогда как ресурсы JavaScript находятся в разных местах на сервере в зависимости от набора конкретных параметров. Последующие ресурсы JavaScript полагаются на эти переменные ресурсы, и такие файлы ДОЛЖНЫ быть гарантированы для загрузки до загрузки других зависимых файлов, тем самым делая приложение целым.
Этот фундамент идеи действительно расширяется на ответ vol7ron. Процедуры, основанные на транзакциях, на самом деле являются единственным временем, когда должны выполняться синхронные запросы. В большинстве других случаев асинхронные вызовы являются лучшей альтернативой, в которой после вызова DOM обновляется по мере необходимости. Во многих случаях, таких как пользовательские системы, у вас могут быть определенные функции, заблокированные для "неавторизованных пользователей" до тех пор, пока они сами не войдут в систему. Эти функции после асинхронного вызова разблокируются с помощью процедуры обновления DOM.
Наконец-то я должен сказать, что согласен с большинством отдельных лиц по этому вопросу: везде, где это возможно, следует избегать синхронных запросов XHR, поскольку, как он работает, браузер блокируется синхронными вызовами. При реализации синхронных запросов они должны выполняться таким образом, чтобы браузер, как правило, был заблокирован, в любом случае, в разделе HEAD, прежде чем загрузка страницы действительно произойдет.
Ответ 6
Существует множество случаев реального мира, когда блокировка пользовательского интерфейса является именно желаемым поведением.
Возьмите приложение с несколькими полями, а некоторые поля должны быть подтверждены вызовом xmlhttp на удаленный сервер, который будет вводить это значение поля и другие значения полей.
В синхронном режиме логика проста, блокировка, испытываемая пользователем, очень короткая и нет проблем.
В асинхронном режиме пользователь может изменять значения любых других полей, пока первый проверяется. Эти изменения вызовут другие вызовы xmlhttp со значениями из начального поля, еще не подтвержденного. Что произойдет, если начальная проверка не прошла? Чистый беспорядок. Если режим синхронизации становится устаревшим и запрещенным, логика приложения становится кошмаром для обработки. В основном приложение должно быть переписано для управления блокировками (например, отключить другие элементы во время процессов проверки). Сложность кода значительно возрастает. Несоблюдение этого может привести к сбою логики и, в конечном итоге, повреждению данных.
В основном возникает вопрос: что более важно, незаблокированный пользовательский интерфейс или риск повреждения данных? Ответ должен оставаться с разработчиком приложения, а не с W3C.
Ответ 7
В некоторых случаях jQuery использует синхронный AJAX. При вставке HTML, который содержит сценарии, браузер не будет их выполнять. Сценарии необходимо выполнить вручную. Эти скрипты могут прикреплять обработчики кликов. Предположим, что пользователь нажимает на элемент до присоединения обработчика, и страница не будет функционировать должным образом. Поэтому для предотвращения условий гонки синхронный AJAX будет использоваться для извлечения этих сценариев. Поскольку синхронный AJAX эффективно блокирует все остальное, он может быть уверен, что сценарии и события выполняются в правильном порядке.
Ответ 8
По состоянию на 2015 год приложения для javascript для настольных компьютеров становятся все более популярными. Обычно в этих приложениях при загрузке локальных файлов (и загрузка их с использованием XHR является вполне допустимым параметром) скорость загрузки происходит настолько быстро, что мало смысла переуплотывать код с помощью async. Конечно, могут быть случаи, когда async - это способ пойти (запрашивать контент из Интернета, загружать действительно большие файлы или огромное количество файлов в одной партии), но в противном случае синхронизация работает просто отлично (и намного проще в использовании).
Ответ 9
Что произойдет, если вы выполните синхронный вызов в производственном коде?
Небо падает.
Серьезно, пользователю не нравится заблокированный браузер.
Ответ 10
Я использую его для проверки имени пользователя во время проверки того, что имя пользователя уже не существует.
Я знаю, что было бы лучше сделать это асинхронно, но тогда я должен использовать другой код для этого конкретного правила проверки. Я объясняю лучше. В моей настройке проверки используются некоторые функции проверки, которые возвращают true или false, в зависимости от того, действительны ли данные.
Поскольку функция должна возвращаться, я не могу использовать асинхронные методы, поэтому я просто делаю это синхронно и надеюсь, что сервер ответит достаточно быстро, чтобы не быть слишком заметным. Если бы я использовал обратный вызов AJAX, тогда мне пришлось бы обрабатывать остальную часть выполнения иначе, чем другие методы проверки.
Ответ 11
Иногда у вас есть действие, которое зависит от других. Например, действие B может быть запущено только в том случае, если A закончен. Синхронный подход обычно используется, чтобы избежать условий гонки. Иногда использование синхронного вызова - это более простая реализация, а затем создание сложной логики для проверки каждого состояния ваших асинхронных вызовов, которые зависят друг от друга.
Проблема с этим подходом заключается в том, что вы "блокируете" пользовательский браузер до завершения действия (пока запрос не вернется, не закончит, не загрузит и т.д.). Поэтому будьте осторожны при использовании.
Ответ 12
Я использую синхронные вызовы при разработке кода - независимо от того, что вы делали во время коммутации запроса и с сервера, может скрывать причину ошибки.
Когда он работает, я делаю его асинхронным, но я пытаюсь включить таймер прерывания и обратные вызовы сбоев, потому что вы никогда не знаете...
Ответ 13
XMLHttpRequest
традиционно используется для асинхронных запросов. Иногда (для отладки или конкретной бизнес-логики) вы хотите изменить все/несколько асинхронных вызовов на одной странице для синхронизации.
Вы хотели бы сделать это, не изменяя все в своем JS-коде. Флаг async/sync дает вам эту возможность, и если она разработана правильно, вам нужно изменить только одну строку в коде или изменить значение одного var
во время выполнения.
Ответ 14
Причина:
Предположим, что у вас есть приложение ajax, которое должно выполнять полдюжины http, чтобы загрузить различные данные с сервера, прежде чем пользователь сможет осуществлять какое-либо взаимодействие.
Очевидно, что вы хотите, чтобы это вызвало onload.
Синхронные вызовы работают очень хорошо для этого без какой-либо дополнительной сложности для кода. Это просто и понятно.
Минус:
Единственным недостатком является то, что ваш браузер блокируется до тех пор, пока все данные не будут загружены или не произойдет тайм-аут. Что касается рассматриваемого приложения ajax, это не является большой проблемой, потому что приложение бесполезно до тех пор, пока все исходные данные не будут загружены.
Alternative?
Тем не менее, многие браузеры блокируют все окна/вкладки, когда javascript занят в любом из них, что является глупой проблемой дизайна браузера, но в результате блокирование, возможно, медленной загрузки сети не является вежливым, если оно удерживает пользователей от используя другие вкладки, ожидая загрузки страницы ajax.
Однако, похоже, что синхронные get были удалены или ограничены в последних браузерах. Я не уверен, что это потому, что кто-то решил, что они всегда были плохими, или если авторы браузера были смущены рабочим проектом WC по этой теме.
http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method делает его похожим (см. раздел 4.7.3) вам не разрешено устанавливать таймаут при использовании режима блокировки. Кажется, что интуитивно понятно мне: всякий раз, когда кто-то блокирует IO, он вежлив, чтобы установить разумный тайм-аут, поэтому зачем блокировать io, но не с указанным пользователем таймаутом?
Мое мнение состоит в том, что блокирование IO играет жизненно важную роль в некоторых ситуациях, но должно быть выполнено правильно. Хотя для одной вкладки или окна браузера неприемлемо блокировать все другие вкладки или окна, это ошибка дизайна браузера. Позор, когда стыдно. Но в некоторых случаях вполне приемлемо, чтобы отдельная вкладка или окно не реагировала на пару секунд (то есть, используя блокировку IO/HTTP GET) в некоторых ситуациях - например, при загрузке страницы, возможно, много данных должно быть, прежде чем что-либо может быть сделано в любом случае. Иногда правильно реализованный код блокировки - самый чистый способ сделать это.
Конечно, эквивалентная функция в этом случае может быть получена с использованием асинхронных http-получателей, но какой тип тупой процедуры требуется?
Думаю, я бы попробовал что-то в этом направлении:
При загрузке документа выполните следующие действия:
1: Настройте 6 глобальных переменных "Готово", инициализированных до 0.
2: Выполнить все 6 фоновых снимков (Предполагая, что порядок не имеет значения)
Затем обратные вызовы завершения для каждого из 6 http get будут устанавливать соответствующие флаги "Done".
Кроме того, каждый обратный вызов проверяет все остальные флаги, чтобы проверить, завершено ли все 6 HTTP-запросов. Последний обратный вызов для завершения, увидев, что все остальные завершены, затем вызовет функцию REAL init, которая затем установит все, теперь, когда все данные будут извлечены.
Если порядок выборки имел значение - или если веб-сервер не смог принять несколько запросов одновременно, тогда вам понадобится что-то вроде этого:
В onload() будет запущен первый http get.
В этом обратном вызове будет запущен второй.
В нем обратный вызов, третий - и т.д. И т.д., Причем каждый обратный вызов запускает следующий HTTP GET. Когда последний вернется, он вызовет настоящую процедуру init().
Ответ 15
Firefox (и, возможно, все браузеры, отличные от IE) не поддерживает async XHR timeOut.
HTML5 WebWorkers поддерживают таймауты. Таким образом, вам может потребоваться привязать запрос XHR синхронизации к WebWorker с тайм-аутом для реализации async-подобного XHR с поведением тайм-аута.
Ответ 16
У меня была ситуация, когда асинхронные запросы для списка URL-адресов, вызываемых последовательно с использованием forEach (и цикла for), заставили бы остальные запросы быть отменены. Я переключился на синхронный, и они работают по назначению.
Ответ 17
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!');
}
});
Таким образом, просто факт, что 2 или три вещи должны произойти по порядку, не является основанием для их синхронного (хотя для большинства людей проще работать с кодом синхронизации).
ПОЧЕМУ ИСПОЛЬЗУЕТ СИНХРОННЫЙ 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
, так как это последняя функция из вашего приложения, которое когда-либо будет выполняться раньше окно закрывается.
Я НЕ НУЖДАЮТ СИНХРОТИЧЕСКИЕ ЗВОНКИ, НО Я ИСПОЛЬЗУЮ ИХ В КАКИХ-ЛИБО, КАК ОНИ ЛЕГКО
Пожалуйста, не надо. Синхронные вызовы блокируют ваш браузер и делают приложение неприемлемым. Но ты прав. Асинхронный код сложнее. Существует, однако, способ облегчить дело с ним. Не так просто, как код синхронизации, но он приближается: Promise s.
Вот пример: два асинхронных вызова должны быть успешно завершены до того, как может работать третий сегмент кода:
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 с Promises.
Ответ 18
Ну вот одна хорошая причина. Я хотел сделать http-запрос, тогда, в зависимости от результата, вызовите click() в файле input type =. Это невозможно при асинхронном xhr или выборке. Обратный вызов теряет контекст "действие пользователя", поэтому вызов click() игнорируется. Синхронный xhr спас мой бекон.
onclick(event){
//here I can, but I don't want to.
//document.getElementById("myFileInput").click();
fetch("Validate.aspx", { method : "POST", body: formData, credentials: "include" })
.then((response)=>response.json())
.then(function (validResult) {
if (validResult.success) {
//here, I can't.
document.getElementById("myFileInput").click();
}
});
}