Кажется, что почти все выполняют асинхронные запросы с помощью XMLHttpRequest, но, очевидно, тот факт, что существует возможность выполнять синхронные запросы, указывает на то, что для этого может быть веская причина. Так в чем же может быть причина?
javascript
ajax
Даррелл Брогдон
источник
источник
Ответы:
Я думаю, что они могут стать более популярными по мере развития стандартов HTML 5. Если веб-приложению будет предоставлен доступ к веб-воркерам, я могу предвидеть, что разработчики будут использовать выделенного веб-воркера для выполнения синхронных запросов, как сказал Джонатан, чтобы гарантировать, что один запрос выполняется раньше другого. С текущей ситуацией с одним потоком это далеко не идеальный дизайн, так как он блокируется до завершения запроса.
источник
Синхронные XHR полезны для сохранения пользовательских данных. Если вы обрабатываете
beforeunload
событие, вы можете загружать данные на сервер, когда пользователь закрывает страницу.Если бы это было сделано с использованием опции async, то страница могла бы закрыться до завершения запроса. Выполнение этого синхронно гарантирует, что запрос завершится или завершится ошибкой ожидаемым образом.
источник
Обновить:
Приведенное ниже намекает - но безуспешно в доставке - что с появлением улучшенной обработки асинхронных запросов действительно нет причин использовать синхронные запросы, если только мы не намерены намеренно блокировать действия пользователей до тех пор, пока запрос не будет завершен - звучит злонамеренно: )
Хотя это может показаться плохим, могут быть случаи, когда важно, чтобы запрос (или серия запросов) происходил до того, как пользователь покинет страницу или до того, как будет выполнено действие - блокирование выполнения другого кода (например, предотвращение кнопки возврата) может возможно уменьшить количество ошибок / обслуживания плохо спроектированной системы; Тем не менее, я никогда не видел этого в дикой природе и подчеркиваю, что этого следует избегать.
Библиотеки, как и обещания , симулируют синхронность, объединяя процессы в цепочку обратных вызовов. Это соответствует большинству потребностей разработки, когда желательно иметь упорядоченные неблокирующие события, которые позволяют браузерам сохранять отзывчивость для пользователя (хороший UX).
Как указано в документации Mozilla, бывают случаи, когда вам необходимо использовать синхронные запросы; однако также указан обходной путь, использующий маяк (недоступный в IE / Safari) для таких случаев. Хотя это экспериментально, но если оно когда-либо достигнет стандартов, то, возможно, сможет забить гвоздь в гроб синхронных запросов.
Вы хотели бы выполнять синхронные вызовы при любом виде обработки, подобной транзакции, или там, где требуется любой порядок операций.
Например, предположим, что вы хотите настроить событие для выхода из системы после воспроизведения песни. Если сначала произойдет выход из системы, песня никогда не будет воспроизводиться. Это требует синхронизации запросов.
Другой причиной может быть работа с WebService, особенно при выполнении математических операций на сервере.
Очень редко синхронный вызов может быть оправдан на обычном примере из реальной жизни. Возможно, если щелкнуть логин, а затем щелкнуть часть сайта, для которой требуется, чтобы пользователь вошел в систему.
Как уже говорили другие, это свяжет ваш браузер, поэтому держитесь подальше от него, где можете.
Однако вместо синхронных вызовов пользователи часто хотят остановить загружаемое в данный момент событие, а затем выполнить другую операцию. В некотором роде это синхронизация, поскольку первое событие завершается до начала второго. Для этого используйте метод abort () для объекта подключения xml.
источник
Я бы сказал, что если вы считаете, что заблокировать браузер пользователя, пока запрос выполняется приемлемо, обязательно используйте синхронный запрос.
Если вашей целью является сериализация запросов, то это можно сделать с помощью асинхронных запросов, если обратный вызов onComplete вашего предыдущего запроса запустит следующий в строке.
источник
Во многих реальных случаях блокировка пользовательского интерфейса - это именно то, что нужно.
Возьмем приложение с несколькими полями, и некоторые поля должны быть проверены вызовом xmlhttp на удаленный сервер, предоставляющий в качестве входных данных значение этого поля и значения других полей.
В синхронном режиме логика проста, блокировка, которую испытывает пользователь, очень короткая и нет никаких проблем.
В асинхронном режиме пользователь может изменять значения любых других полей, пока проверяется исходное. Эти изменения вызовут другие вызовы xmlhttp со значениями из начального поля, которые еще не проверены. Что произойдет, если первоначальная проверка не удалась? Чистый беспорядок. Если режим синхронизации становится устаревшим и запрещенным, логика приложения становится кошмаром. В основном приложение должно быть переписано для управления блокировками (например, отключение других элементов во время процессов проверки). Сложность кода чрезвычайно возрастает. Невыполнение этого может привести к логическому сбою и, в конечном итоге, к повреждению данных.
По сути, возникает вопрос: что важнее, незаблокированный пользовательский интерфейс или риск повреждения данных? Ответ должен оставаться за разработчиком приложения, а не с W3C.
источник
Я вижу, как можно использовать синхронные запросы XHR, когда ресурс в переменном местоположении должен быть загружен до других статических ресурсов на странице, которые зависят от первого ресурса для полноценного функционирования. Фактически, я реализую такой запрос XHR в собственном небольшом подпроекте, в то время как ресурсы JavaScript находятся в различных местах на сервере в зависимости от набора определенных параметров. Последующие ресурсы JavaScript полагаются на эти переменные ресурсы, и такие файлы ДОЛЖНЫ быть гарантированы для загрузки до загрузки других зависимых файлов, что делает приложение единым.
Эта основа идеи действительно расширяет ответ vol7ron. На самом деле, процедуры на основе транзакций - единственный случай, когда следует выполнять синхронные запросы. В большинстве других случаев лучшей альтернативой являются асинхронные вызовы, при которых после вызова DOM обновляется по мере необходимости. Во многих случаях, например в пользовательских системах, вы можете заблокировать определенные функции для «неавторизованных пользователей» до тех пор, пока они сами по себе не войдут в систему. Эти функции после асинхронного вызова разблокируются с помощью процедуры обновления DOM.
Я должен наконец сказать, что я согласен с точками зрения большинства людей по этому поводу: по возможности следует избегать синхронных запросов XHR, поскольку в зависимости от того, как он работает, браузер блокируется синхронными вызовами. При реализации синхронных запросов они должны выполняться таким образом, чтобы браузер обычно был заблокирован, в любом случае, скажем, в разделе HEAD до фактической загрузки страницы.
источник
С 2015 года настольные приложения на javascript становятся все более популярными. Обычно в этих приложениях при загрузке локальных файлов (и загрузка их с помощью XHR - вполне допустимый вариант) скорость загрузки настолько высока, что нет смысла чрезмерно усложнять код с помощью async. Конечно, могут быть случаи, когда асинхронный режим является подходящим (запрос контента из Интернета, загрузка действительно больших файлов или огромного количества файлов в одном пакете), но в остальном синхронизация работает нормально (и ее намного проще использовать) .
источник
jQuery при некоторых обстоятельствах использует синхронный AJAX внутри компании. При вставке HTML-кода, содержащего скрипты, браузер не выполнит их. Скрипты нужно запускать вручную. Эти скрипты могут присоединять обработчики кликов. Предположим, что пользователь щелкает элемент до того, как будет прикреплен обработчик, и страница не будет работать должным образом. Следовательно, чтобы предотвратить состояние гонки, для получения этих сценариев будет использоваться синхронный AJAX. Поскольку синхронный AJAX эффективно блокирует все остальное, можно быть уверенным, что сценарии и события выполняются в правильном порядке.
источник
Причина:
Предположим, у вас есть приложение ajax, которому необходимо выполнить полдюжины HTTP-запросов для загрузки различных данных с сервера, прежде чем пользователь сможет выполнить какое-либо взаимодействие.
Очевидно, вы хотите, чтобы это запускалось при загрузке.
Для этого очень хорошо работают синхронные вызовы, не усложняя код. Это просто и понятно.
Недостаток:
Единственный недостаток заключается в том, что ваш браузер блокируется до тех пор, пока не будут загружены все данные или не истечет время ожидания. Что касается рассматриваемого приложения ajax, это не большая проблема, потому что приложение бесполезно, пока все исходные данные не будут загружены.
Альтернатива?
Однако многие браузеры блокируют все окна / вкладки, когда javascript занят в любом из них, что является глупой проблемой дизайна браузера, но в результате блокировка, возможно, медленной сети, становится не вежливой, если она не позволяет пользователям использовать другие вкладки ожидая загрузки страницы ajax.
Однако похоже, что синхронное получение было удалено или ограничено в последних браузерах. Я не уверен, что это потому, что кто-то решил, что они всегда были плохими, или разработчики браузеров были сбиты с толку рабочим проектом WC по этой теме.
http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method делает вид, что (см. раздел 4.7.3) вам не разрешено устанавливать тайм-аут при использовании режима блокировки . Мне кажется, счетчик интуитивно понятен: всякий раз, когда кто-то блокирует ввод-вывод, вежливо установить разумный тайм-аут, так зачем разрешать блокировку io, но не с указанным пользователем таймаутом?
Я считаю, что блокировка ввода-вывода играет жизненно важную роль в некоторых ситуациях, но должна быть реализована правильно. Хотя для одной вкладки или окна браузера недопустимо блокировать все остальные вкладки или окна, это недостаток дизайна браузера. Позор там, где стыд. Но в некоторых случаях вполне допустимо, чтобы отдельная вкладка или окно не реагировали в течение нескольких секунд (например, с использованием блокировки ввода-вывода / HTTP GET) в некоторых ситуациях - например, при загрузке страницы, возможно, много данных должно быть, прежде чем что-либо можно будет сделать. Иногда правильно реализованный блокирующий код - самый чистый способ сделать это.
Конечно, эквивалентная функция в этом случае может быть получена с использованием асинхронных HTTP-запросов, но какая глупая процедура требуется?
Думаю, я бы попробовал что-нибудь в этом роде:
При загрузке документа выполните следующие действия: 1: Установите 6 глобальных переменных флага «Готово», инициализированных в 0. 2: Выполните все 6 фоновых запросов (при условии, что порядок не имеет значения)
Затем обратные вызовы завершения для каждого из 6 HTTP-запросов установят соответствующие флаги «Готово». Кроме того, каждый обратный вызов будет проверять все остальные флаги выполнения, чтобы узнать, завершены ли все 6 HTTP-запросов. Последний завершенный обратный вызов, увидев, что все остальные завершились, затем вызовет функцию REAL init, которая затем все настроит, теперь, когда все данные были получены.
Если порядок выборки имеет значение или если веб-сервер не может принимать несколько запросов одновременно, вам понадобится что-то вроде этого:
В onload () будет запущено первое получение http. В этом обратном вызове будет запущен второй. В этом обратном вызове третий - и так далее, и так далее, причем каждый обратный вызов запускает следующий HTTP GET. Когда вернется последний, он вызовет настоящую процедуру init ().
источник
Что произойдет, если вы сделаете синхронный вызов в производственном коде?
Небо падает.
Нет, серьезно, пользователю не нравится заблокированный браузер.
источник
Я использую его для проверки имени пользователя во время проверки того, что имя пользователя еще не существует.
Я знаю, что было бы лучше сделать это асинхронно, но тогда я должен использовать другой код для этого конкретного правила проверки. Я лучше объясню. Моя настройка проверки использует некоторые функции проверки, которые возвращают истину или ложь, в зависимости от того, действительны ли данные.
Поскольку функция должна возвращаться, я не могу использовать асинхронные методы, поэтому я просто делаю это синхронным и надеюсь, что сервер ответит достаточно быстро, чтобы не быть слишком заметным. Если бы я использовал обратный вызов AJAX, мне пришлось бы обрабатывать остальную часть выполнения иначе, чем другие методы проверки.
источник
false
) и просто устанавливать для него значение true или false, когда сервер отвечает. при смене поля вы сбрасываете флаг и снова вызываете сервер.Иногда у вас есть действие, которое зависит от других. Например, действие B может быть запущено, только если A завершено. Синхронный подход обычно используется, чтобы избежать состояния гонки. . Иногда использование синхронного вызова является более простой реализацией, чем создание сложной логики для проверки каждого состояния ваших асинхронных вызовов, которые зависят друг от друга.
Проблема с этим подходом состоит в том, что вы «блокируете» браузер пользователя до тех пор, пока действие не будет завершено (пока запрос не вернется, не завершится, не загрузится и т. Д.). Так что будьте осторожны при его использовании.
источник
Я использую синхронные вызовы при разработке кода - все, что вы делали во время передачи запроса на сервер и с сервера, может скрыть причину ошибки.
Когда он работает, я делаю его асинхронным, но я пытаюсь включить таймер прерывания и обратные вызовы отказа, потому что вы никогда не знаете ...
источник
SYNC vs ASYNC: в чем разница?
В основном это сводится к следующему:
console.info('Hello, World!'); doSomething(function handleResult(result) { console.info('Got result!'); }); console.info('Goodbye cruel world!');
Когда
doSomething
это синхронное это будет печатать:Напротив, если
doSomething
это асинхронно , это напечатает:Поскольку функция
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
событие, поскольку это последняя функция из вашего приложения, которая когда-либо будет запущена до закрытия окна.МНЕ НЕ НУЖНЫ СИНХРОНИЗАЦИОННЫЕ ЗВОНКИ, НО Я ИСПОЛЬЗУЮ ИХ, КАК ОНИ ПРОЩЕ
Пожалуйста, не надо. Синхронные вызовы блокируют ваш браузер, и приложение перестает отвечать на запросы. Но ты прав. Асинхронный код сложнее. Однако есть способ сделать это намного проще. Не так просто, как код синхронизации, но приближается: 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 с обещаниями .
источник
XMLHttpRequest
традиционно используется для асинхронных запросов. Иногда (для отладки или конкретной бизнес-логики) вы хотите изменить все / несколько асинхронных вызовов на одной странице для синхронизации.Вы бы хотели сделать это, не меняя всего в своем JS-коде. Флаг async / sync дает вам эту возможность, и если он правильно спроектирован, вам нужно изменить только одну строку в вашем коде / изменить значение одной
var
во время выполнения.источник
Firefox (и, вероятно, все браузеры, отличные от IE) не поддерживает асинхронный XHR timeOut.
HTML5 WebWorkers поддерживает тайм-ауты. Итак, вы можете захотеть обернуть запрос синхронизации XHR в WebWorker с тайм-аутом, чтобы реализовать асинхронный XHR с тайм-аутом.
источник
У меня была ситуация, когда асинхронные запросы для списка URL-адресов, вызываемых последовательно с использованием forEach (и цикла for), приводили к отмене оставшихся запросов. Я перешел на синхронный, и они работают по назначению.
источник
Использование синхронных HTTP-запросов - обычная практика в бизнесе мобильной рекламы.
Компании (также известные как «Издатели»), которые создают приложения, часто размещают рекламу для получения дохода. Для этого они устанавливают рекламные SDK в свое приложение. Многие из них существуют (MoPub, Ogury, TapJob, AppNext, Google Ads AdMob).
Эти SDK будут показывать рекламу в веб-просмотре.
Показ рекламы пользователю должен быть приятным , особенно при воспроизведении видео. Ни в какой момент не должно быть буферизации или загрузки.
Для решения этого
precaching
используется. Где медиа (изображение / видео / и т. Д.) Загружаются синхронно в фоновом режиме веб-просмотра.Почему бы не сделать это асинхронно?
onload
событие, чтобы узнать, когда объявление «готово» к показу пользователю.С прекращением поддержки синхронных запросов XMLHttpRequests рекламный бизнес, скорее всего, будет вынужден изменить стандарт в будущем, если не удастся найти другой способ.
источник
Синхронный XHR может быть очень полезен для (непроизводственных) внутренних инструментов и / или разработки фреймворков. Представьте, например, что вы хотите синхронно загрузить библиотеку кода при первом доступе, например:
get draw() { if (!_draw) { let file; switch(config.option) { case 'svg': file = 'svgdraw.js'; break; case 'canvas': file = 'canvasdraw.js'; break; default: file = 'webgldraw.js'; } var request = new XMLHttpRequest(); request.open('GET', file, false); request.send(null); _draw = eval(request.responseText); } return _draw; }
Прежде чем впадать в волнение и слепо извергать зло eval, имейте в виду, что это только для локального тестирования. Для производственных сборок _draw уже будет установлен.
Итак, ваш код может выглядеть так:
foo.drawLib.draw.something(); //loaded on demand
Это всего лишь один пример того, что было бы невозможно сделать без синхронизации XHR. Вы можете загрузить эту библиотеку заранее, да, или выполнить обещание / обратный вызов, но вы не можете загрузить библиотеку синхронно без синхронизации XHR. Подумайте, насколько такие вещи могут очистить ваш код ...
Пределы того, что вы можете сделать с этим для инструментов и фреймворков (работающих локально), ограничены только вашим воображением. Хотя, похоже, воображение в мире JavaScript немного ограничено.
источник
Вот одна веская причина. Я хотел сделать http-запрос, а затем, в зависимости от результата, вызвать click () для input type = file. Это невозможно с асинхронным 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(); } }); }
источник