javascript - ejemplo - xmlhttprequest post json
Implementación de un objeto XMLHttpRequest de restablecimiento automático (7)
@stu
En esta aplicación, el tiempo de respuesta es clave: en realidad, lo importante es que todos los clientes se actualicen simultáneamente (o lo más cerca posible).
el número de conexiones desconectadas será bastante limitado ~ 50max y el intervalo entre los cambios podría ser de varios minutos.
Si se utiliza el sondeo, necesitaría ser muy corto ~ 100 ms, lo que llevaría a una gran cantidad de solicitudes innecesarias (lo cual será costoso para el pequeño servidor de socket php que he improvisado; lo sé, sé que python sería mejor para el servidor pero no lo sé lo suficientemente bien)
Estoy tratando de implementar un estilo de cometa, una larga conexión de sondeo usando un objeto XMLHttpResponse. La idea es mantener una conexión abierta a un servidor que envíe datos cuando esté disponible (falsificación). Tan pronto como el objeto XHR se complete, necesito generar uno nuevo para esperar cualquier dato nuevo.
A continuación hay un fragmento de código que describe una solución que funciona, pero, como dice el comentario, solo debido a un tiempo de espera del que debo deshacerme.
window.onload = function(){
XHR.init();
}
XHR = {
init: function() {
this.xhr = new XMLHttpRequest();
this.xhr.open( "GET", "proxy.php?salt="+Math.round( Math.random()*10000 ), true );
this.xhr.onreadystatechange = this.process.bind( this );
this.xhr.send( null );
},
process: function() {
if( this.xhr.readyState == 4 ) {
// firebug console
console.log( this.xhr.responseText );
// ** Attempting to create new XMLHttpRequest object to
// replace the one that''s just completed
// doesn''t work without the timeout
setTimeout( function() { this.init() }.bind( this ), 1000 );
}
}
}
Function.prototype.bind = function( obj ) {
var method = this;
return function() {
return method.apply( obj, arguments );
}
}
// proxy.php - a dummy that keeps the XHR object waiting for a response
<?php
$rand = mt_rand( 1, 10 );
sleep( $rand );
echo date( ''H:i:s'' ).'' - ''.$rand;
Creo que el problema podría ser que no se puede eliminar un objeto (xhr) de su propio manejador de eventos (proceso) como es el caso aquí. especialmente porque el ''this'' dentro del controlador está vinculado a un objeto (XHR) que contiene el objeto (xhr) que intento eliminar. Un poco circular!
¿Alguien puede ayudar? El ejemplo anterior es lo más cercano que puedo obtener.
Lo que estás haciendo es un sondeo efectivo, ¿por qué hacerlo más complejo de lo que necesita ser y simplemente sondear cada pocos segundos? O cada segundo, ¿cuánto tiempo está realmente ahorrando y realmente es tan importante, y va a estar bloqueando un montón de sockets en el extremo del servidor si tiene muchos usuarios?
Es posible que le resulte más fácil implementar la reutilización, agregando el método abort()
:
XHR = {
init: function() {
if (!this.xhr) { // setup only once
this.xhr = new XMLHttpRequest();
this.xhr.onreadystatechange = this.process.bind( this );
}
this.xhr.abort(); // reset xhr
this.xhr.open(/*...*/);
this.xhr.send(null);
},
process: function() {
if( this.xhr.readyState == 4 ) {
// firebug console
console.log( this.xhr.responseText );
// start next round
this.init();
}
}
};
@meouw [comentario]
Si obtiene el mismo resultado, entonces supongo que tiene un problema de caché (que Math.random()
no está resolviendo) o no está marcando lo que se ha enviado en solicitudes anteriores (reenviando los mismos datos) cada vez).
Solo usa jquery y haz algo como esto:
function getData() {
$.getJSON(someUrl, gotData);
}
// Whenever a query stops, start a new one.
$(document).ajaxStop(getData, 0);
// Start the first query.
getData();
Mis ejemplos slosh hacen esto (ya que es más o menos un servidor de cometas).
Probablemente no deberías usar XMLHTTPRequest para nada.
Hace varios años, mucho antes de que se conociera XMLHTTPRequest, creé un programa de chat para usar en un navegador normal. La ventana con el chat estaba en un marco donde los datos provienen de un script cgi que nunca terminó. Siempre que había datos nuevos, simplemente los envié y se mostraron inmediatamente en el cliente.
Supongo que puedes usar algo similar hoy:
- Crea una función en tu página que hará la actualización.
- Crea un IFRAME, puedes hacerlo invisible si quieres
- Establezca el origen de IFRAME en su secuencia de comandos que genera los datos
Los datos podrían estar encapsulados en etiquetas SCRIPT. Si recuerdo correctamente, los navegadores requieren tener todo el contenido de la etiqueta del script antes de intentar evaluarlo. Llame a su función de actualización:
<script type="text/javascript">myupdate("mydata");</script>
- Incluso si no tiene algo para enviar, envíe un espacio cada 5 segundos o más para restablecer el tiempo de espera en el navegador.
- Si mal no recuerdo, tuvo que enviar aproximadamente 1K de datos al comienzo de la transacción para llenar el búfer de captación previa en el navegador (tal vez esto se debe aumentar en los navegadores de hoy)
Simplemente agregue xhr = null
dentro de la función init
. Al xhr
se le asignará una nueva conexión, y por lo tanto no tomará el valor anterior de HTTPRequest
.
init: function() {
xhr = null;
this.xhr = new XMLHttpRequest();
this.xhr.open( "GET", "proxy.php?salt="+Math.round( Math.random()*10000 ), true );
this.xhr.onreadystatechange = this.process.bind( this );
this.xhr.send( null );
},
Pero para intentar responder a su pregunta, la forma de eliminar cosas que no son esto es configurar un temporizador para llamar a una función que elimina, de esa manera, no se está eliminando.