¿Hay alguna razón para usar un XMLHttpRequest síncrono?


Parece que casi todo el mundo hace peticiones asíncronas con XMLHttpRequest, pero obviamente el hecho de que existe la capacidad de hacer peticiones síncronas indica que podría haber una razón válida para hacerlo. Entonces, ¿cuál podría ser esa razón válida?

Author: Darrell Brogdon, 2010-01-18

18 answers

Creo que podrían volverse más populares a medida que avanzan los estándares HTML 5. Si a una aplicación web se le da acceso a los trabajadores web, podría prever que los desarrolladores usen un trabajador web dedicado para hacer solicitudes sincrónicas, como dijo Jonathan, para garantizar que una solicitud ocurra antes que otra. Con la situación actual de un hilo, es un diseño menos que ideal, ya que se bloquea hasta que se completa la solicitud.

 25
Author: D.C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-11 12:38:42

Los XHR síncronos son útiles para guardar datos de usuario. Si maneja el evento beforeunload, puede cargar datos en el servidor a medida que el usuario cierra la página.

Si esto se hizo usando la opción async, entonces la página podría cerrarse antes de que se complete la solicitud. Hacer esto de forma sincrónica garantiza que la solicitud se complete o falle de la manera esperada.

 29
Author: Sami Samhuri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-04 16:40:08

Actualización:

Lo siguiente insinuó-pero no tuvo éxito en la entrega - que con el advenimiento de un mejor manejo de solicitudes asíncronas, realmente no hay razón para usar solicitudes síncronas, a menos que tenga la intención de bloquear deliberadamente a los usuarios para que no hagan nada hasta que se complete una solicitud-suena malicioso:)

Aunque esto puede sonar mal, puede haber momentos en los que es importante que una solicitud (o serie de solicitudes) ocurra antes de que un usuario abandone una página, o antes de que se realice una acción realizado-bloquear otra ejecución de código (por ejemplo, prevenir el botón atrás) podría reducir errores/mantenimiento para un sistema mal diseñado; dicho esto, nunca lo he visto en el salvaje y enfatizar que debe evitarse.

Las bibliotecas

, como promise, fingen sincronicidad encadenando procesos a través de callbacks. Esto se adapta a la mayoría de las necesidades de desarrollo donde el deseo es tener eventos ordenados, no bloqueantes que permitan a los navegadores retener capacidad de respuesta para el usuario (buena experiencia de usuario).

Como se indica en los documentos de Mozilla hay casos en los que tiene que usar solicitudes síncronas; sin embargo, también se muestra una solución alternativa que utiliza beacon (no disponible en IE/Safari) para tales casos. Si bien esto es experimental, si alguna vez alcanza los estándares de aceptación, posiblemente podría poner un clavo en el ataúd de solicitud sincrónica.


Te gustaría realizar llamadas síncronas en cualquier tipo de procesamiento similar a una transacción, o donde sea necesario cualquier orden de operación.

Por ejemplo, supongamos que desea personalizar un evento para cerrar sesión después de reproducir una canción. Si la operación de cierre de sesión se produce primero, entonces la canción nunca se reproducirá. Esto requiere sincronizar las solicitudes.

Otra razón sería cuando se trabaja con un servicio WEB, especialmente cuando se realizan matemáticas en el servidor.

Ejemplo: El servidor tiene una variable con un valor de 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

Si paso (2) ocurre primero, luego el valor final es 2, no 8; por lo tanto, el orden de operación importa y se necesita sincronización.


Hay muy pocas veces que una llamada síncrona puede ser justificada en un ejemplo común del mundo real. Tal vez al hacer clic en iniciar sesión y luego hacer clic en una parte del sitio que requiere que un usuario inicie sesión.

Como otros han dicho, atará su navegador, así que manténgase alejado de él donde pueda.

En lugar de llamadas síncronas, sin embargo, a menudo los usuarios desean detener un evento que se está cargando actualmente y luego realizar alguna otra operación. En cierto modo, esto es sincronización, ya que el primer evento se cierra antes de que comience el segundo. Para ello, utilice el método abort () en el objeto de conexión xml.

 12
Author: vol7ron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-16 05:53:02

Yo diría que si considera bloquear el navegador del usuario mientras la solicitud se completa aceptable, entonces asegúrese de usar una solicitud síncrona.

Si su objetivo es la serialización de las solicitudes, entonces esto se puede lograr usando solicitudes asincrónicas, haciendo que la devolución de llamada onComplete de su solicitud anterior active la siguiente en línea.

 8
Author: hobodave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-18 18:40:15

Puedo ver un uso para las solicitudes XHR síncronas que se utilizarán cuando un recurso en una ubicación variable se debe cargar antes que otros recursos estáticos en la página que dependen del primer recurso para funcionar completamente. De hecho, estoy implementando una solicitud XHR en un pequeño subproyecto propio, mientras que los recursos JavaScript residen en ubicaciones variables en el servidor dependiendo de un conjunto de parámetros específicos. Los recursos JavaScript posteriores dependen de esos recursos variables y dichos archivos SE debe garantizar que se cargue antes de que se carguen los otros archivos de reliant, lo que hace que la aplicación sea completa.

Esa idea foundation realmente amplía la respuesta de vol7ron. Los procedimientos basados en transacciones son realmente el único momento en el que se deben realizar solicitudes sincrónicas. En la mayoría de los otros casos, las llamadas asíncronas son la mejor alternativa en la que, después de la llamada, el DOM se actualiza según sea necesario. En muchos casos, como los sistemas basados en el usuario, podría tener ciertas características bloqueadas para "usuarios no autorizados" hasta que hayan iniciado sesión. Esas características, después de la llamada asincrónica, se desbloquean a través de un procedimiento de actualización DOM.

Finalmente tendría que decir que estoy de acuerdo con los puntos de la mayoría de las personas sobre el asunto: siempre que sea posible, las solicitudes XHR síncronas deben evitarse ya que, con la forma en que funciona, el navegador se bloquea con llamadas síncronas. Al implementar solicitudes síncronas, deben hacerse de una manera en la que el navegador normalmente estaría bloqueado, de todos modos, digamos en la sección HEAD antes de que la página se cargue realmente.

 6
Author: hyponiq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-23 19:07:11

Hay muchos casos del mundo real en los que bloquear la interfaz de usuario es exactamente el comportamiento deseado.

Tome una aplicación con varios campos y algunos campos deben ser validados por una llamada xmlhttp a un servidor remoto que proporcione como entrada el valor de este campo y otros valores de campos.

En modo síncrono, la lógica es simple, el bloqueo experimentado por el usuario es muy corto y no hay problema.

En modo asíncrono, el usuario puede cambiar los valores de cualquier otro campo mientras que la inicial uno está siendo validado. Estos cambios desencadenarán otras llamadas xmlhttp con valores del campo inicial aún no validados. ¿Qué sucede si la validación inicial falló ? Puro desastre. Si el modo de sincronización se vuelve obsoleto y prohibido, la lógica de la aplicación se convierte en una pesadilla para manejar. Básicamente la aplicación tiene que ser reescrita para administrar bloqueos (por ejemplo. deshabilitar otros elementos durante los procesos de validación). La complejidad del código aumenta enormemente. No hacerlo puede conducir a un fallo lógico y en última instancia, la corrupción de datos.

Básicamente la pregunta es: ¿qué es más importante, la experiencia de interfaz de usuario no bloqueada o el riesgo de corrupción de datos ? La respuesta debe permanecer con el desarrollador de la aplicación, no con el W3C.

 5
Author: Alexandre Avrane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-02 16:33:08

JQuery utiliza AJAX síncrono internamente bajo algunas circunstancias. Al insertar HTML que contiene scripts, el navegador no los ejecutará. Los scripts deben ejecutarse manualmente. Estos scripts pueden adjuntar controladores de clics. Supongamos que un usuario hace clic en un elemento antes de que se adjunte el controlador y la página no funcionaría según lo previsto. Por lo tanto, para evitar condiciones de carrera, se usaría AJAX síncrono para obtener esos scripts. Porque el AJAX síncrono efectivamente bloquea todo de lo contrario, puede estar seguro de que los scripts y eventos se ejecutan en el orden correcto.

 4
Author: Henry Chan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-10 16:00:04

A partir de 2015, las aplicaciones javascript de escritorio se están volviendo más populares. Por lo general, en esas aplicaciones cuando se cargan archivos locales (y cargarlos usando XHR es una opción perfectamente válida), la velocidad de carga es tan rápida que no tiene mucho sentido complicar el código con async. Por supuesto, puede haber casos en los que async es el camino a seguir( solicitar contenido de Internet, cargar archivos realmente grandes o una gran cantidad de archivos en un solo lote), pero por lo demás la sincronización funciona bien (y es mucho más fácil de utilizar).

 3
Author: jahu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-25 19:23:46

¿Qué sucede si realiza una llamada síncrona en el código de producción?

El cielo se cae.

No en serio, al usuario no le gusta un navegador bloqueado.

 2
Author: martinr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-18 18:41:33

Lo uso para validar un nombre de usuario, durante la comprobación de que el nombre de usuario no existe ya.

Sé que sería mejor hacerlo asincrónicamente, pero entonces debería usar un código diferente para esta regla de validación en particular. Lo explico mejor. Mi configuración de validación utiliza algunas funciones de validación, que devuelven true o false, dependiendo de si los datos son válidos.

Dado que la función tiene que regresar, no puedo usar técnicas asíncronas, así que solo hago eso sincrónico y espero que el servidor responderá lo suficientemente rápido como para no ser demasiado notable. Si usara una devolución de llamada AJAX, entonces tendría que manejar el resto de la ejecución de manera diferente a los otros métodos de validación.

 2
Author: Andrea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-18 18:41:58

A veces tienes una acción que depende de otras. Por ejemplo, la acción B solo se puede iniciar si A ha finalizado. El enfoque síncrono se utiliza generalmente para evitar condiciones de carrera. A veces, usar una llamada síncrona es una implementación más simple y luego crear una lógica compleja para verificar cada estado de sus llamadas asíncronas que dependen unas de otras.

El problema con este enfoque es que "bloquea" el navegador del usuario hasta que la acción finalice (hasta que la solicitud devuelve, acabados, cargas, etc). Así que tenga cuidado al usarlo.

 2
Author: GmonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-18 18:49:42

Utilizo llamadas síncronas al desarrollar código - lo que sea que haya hecho mientras la solicitud se desplazaba hacia y desde el servidor puede ocultar la causa de un error.

Cuando está funcionando, lo hago asíncrono, pero trato de incluir un temporizador de interrupción y devoluciones de llamada de falla, porque nunca se sabe...

 2
Author: kennebec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-18 22:38:47

Razón:

Supongamos que tiene una aplicación ajax que necesita hacer media docena de http para cargar varios datos del servidor antes de que el usuario pueda realizar cualquier interacción.

Obviamente quieres que esto se active desde onload.

Las llamadas síncronas funcionan muy bien para esto sin ninguna complejidad añadida al código. Es simple y directo.

Inconveniente:

El único inconveniente es que su navegador se bloquea hasta que se cargan todos los datos o se produce un tiempo de espera. En cuanto a la aplicación ajax en cuestión, esto no es un gran problema porque la aplicación no sirve hasta que todos los datos iniciales se cargan de todos modos.

Alternativa?

Sin embargo, muchos navegadores bloquean todas las ventanas/pestañas cuando el javascript está ocupado en cualquiera de ellas, lo cual es un estúpido problema de diseño del navegador, pero como resultado el bloqueo en la red posiblemente lenta no es cortés si evita que los usuarios usen otras pestañas mientras esperan a que se cargue la página ajax.

Sin embargo, parece que se ha eliminado o restringido síncrono gets de los navegadores recientes de todos modos. No estoy seguro de si eso es porque alguien decidió que siempre eran malos, o si los escritores del navegador estaban confundidos por el borrador de trabajo WC sobre el tema.

Http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method hace que parezca (consulte la sección 4.7.3) que no se le permite establecer un tiempo de espera cuando se utiliza el modo de bloqueo. Me parece contra intuitivo: Cada vez que uno hace bloqueo IO es educado establecer un tiempo de espera razonable, así que ¿por qué permitir el bloqueo de io pero no con un tiempo de espera especificado por el usuario?

Mi opinión es que el bloqueo de IO tiene un papel vital en algunas situaciones, pero debe implementarse correctamente. Si bien no es aceptable que una pestaña o ventana del navegador bloquee todas las demás pestañas o ventanas, eso es un defecto de diseño del navegador. Vergüenza donde la vergüenza es debida. Pero es perfectamente aceptable en algunos casos que una pestaña o ventana individual no responda durante un par de segundos (es decir, el uso de bloqueo de IO / HTTP GET) en algunas situaciones for por ejemplo, en la carga de la página, tal vez una gran cantidad de datos debe ser antes de que nada se puede hacer de todos modos. A veces, el código de bloqueo correctamente implementado es la forma más limpia de hacerlo.

Por supuesto, la función equivalente en este caso se puede obtener usando http asíncrono obtiene, pero ¿qué tipo de rutina tonta se requiere?

Supongo que intentaría algo en este sentido:

Al cargar el documento, haga lo siguiente: 1: Establecer 6 global Variables de bandera "Done", inicializadas a 0. 2: Ejecutar todo el fondo 6 gets (Suponiendo que el orden no importa)

Entonces, las devoluciones de llamada de finalización para cada uno de los 6 http get establecerían sus respectivos indicadores "Hecho". Además, cada devolución de llamada verificaría todas las otras banderas hechas para ver si todas las 6 HTTP gets se habían completado. La última devolución de llamada a completar, al ver que todos los demás se habían completado, llamaría a la función de inicio REAL que luego configuraría todo, ahora que los datos eran todos traída.

Si el orden de la búsqueda importaba -- o si el servidor web no podía aceptar varias solicitudes al mismo tiempo need entonces necesitaría algo como esto:

En onload(), se lanzaría el primer http get. En su devolución de llamada, se lanzaría el segundo. En su devolución de llamada, la tercera -- y así sucesivamente y así sucesivamente, con cada devolución de llamada lanzando el siguiente HTTP GET. Cuando el último regresara, llamaría a la rutina init() real.

 2
Author: Jesse Gordon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 21:19:56

XMLHttpRequest se utiliza tradicionalmente para peticiones asíncronas. A veces (para depuración, o lógica de negocio específica) le gustaría cambiar todas/varias de las llamadas asincrónicas en una página para sincronizar.

Te gustaría hacerlo sin cambiar todo en tu código JS. El indicador async/sync le da esa capacidad, y si está diseñado correctamente, solo necesita cambiar una línea en su código/cambiar el valor de uno var durante el tiempo de ejecución.

 2
Author: Itay Moav -Malimovka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-20 16:59:53

Firefox (y probablemente todos los navegadores que no son IE) no admite el tiempo de espera XHR async.

  1. Stackoverflow discusión
  2. Mozilla Firefox XMLHttpRequest

HTML5 WebWorkers soportan tiempos de espera. Por lo tanto, es posible que desee ajustar la solicitud sync XHR a WebWorker con tiempo de espera para implementar XHR asincrónico con comportamiento de tiempo de espera.

 1
Author: Dmitry Kaigorodov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:27

Acabo de tener una situación en la que las solicitudes asincrónicas para una lista de urls llamadas en sucesión usando forEach (y un bucle for) causarían que las solicitudes restantes se cancelaran. Cambié a síncrono y funcionan según lo previsto.

 1
Author: AD Regan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-30 22:52:53

SYNC vs ASYNC: ¿Cuál es la diferencia?

Básicamente se reduce a esto:

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

Cuando doSomething es síncrono esto imprimiría:

Hello, World!
Got result!
Goodbye cruel world!

En contraste, si doSomething es asíncrono , esto imprimiría:

Hello, World!
Goodbye cruel world!
Got result!

Debido a que la función doSomething está haciendo su trabajo de forma asíncrona, regresa antes de que se termine su trabajo. Así que solo obtenemos el resultado después de imprimir Goodbye cruel world!

Si dependemos del resultado de un asíncrono llamada, necesitamos colocar el código dependiendo en la devolución de llamada:

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!');
    }
});

Como tal, solo el hecho de que 2 o tres cosas tienen que suceder en orden no es razón para hacerlo de forma sincrónica (aunque el código de sincronización es más fácil para la mayoría de la gente a trabajar).

¿POR QUÉ USAR SYNCHRONOUS XMLHTTPREQUEST?

Hay algunas situaciones en las que necesita el resultado antes de que se complete la función llamada. Considere este escenario:

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

Supongamos que no tenemos control sobre la llamada código (la línea console.info) y necesita cambiar la función lives para preguntar al servidor... No hay manera de que podamos hacer una solicitud asincrónica al servidor desde lives y aún tener nuestra respuesta antes de que lives se complete. Así que no sabríamos si regresar true o false. La única manera de obtener el resultado antes de que se complete la función es haciendo una solicitud síncrona.

Como menciona Sami Samhuri en su respuesta, un escenario muy real en el que puede necesitar una respuesta a su solicitud de servidor antes de su function terminates es el evento onbeforeunload, ya que es la última función de su aplicación que se ejecutará antes de que se cierre la ventana.

NO NECESITO LLAMADAS DE SINCRONIZACIÓN, PERO LAS USO DE TODOS MODOS, YA QUE SON MÁS FÁCILES

Por favor, no. Las llamadas síncronas bloquean su navegador y hacen que la aplicación no responda. Pero tienes razón. El código asincrónico es más difícil. Hay, sin embargo, una manera de hacer el trato con él mucho más fácil. No es tan fácil como el código de sincronización, pero se está acercando: Promesa s.

Aquí hay un ejemplo: Dos llamadas asíncronas deben completarse con éxito antes de que se ejecute un tercer segmento de código:

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();
});

Así es como implementarías 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.'));
    }
  });
}

Véase también: Escribe mejor JavaScript con Promesas.

 1
Author: Stijn de Witt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-24 12:52:13

Bueno, aquí hay una buena razón. Quería hacer una solicitud http y luego, dependiendo del resultado, llamar a click() en un archivo de entrada type=. Esto no es posible con xhr asíncrono o fetch. La devolución de llamada pierde el contexto "acción del usuario", por lo que la llamada click() es ignorada. Synchronous xhr me salvó el pellejo.

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();
        }
    });
}
 0
Author: bbsimonbb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-23 13:10:54