jQuery, ejemplo de encuesta simple

105

Estoy aprendiendo jQuery y estoy tratando de encontrar un ejemplo de código simple que sondeará una API para una condición. (es decir, solicite una página web cada pocos segundos y procese los resultados)

Estoy familiarizado con cómo hacer AJAX en jQuery, simplemente parece que no puedo encontrar la forma "adecuada" de hacer que se ejecute en un "temporizador".

Miguel
fuente

Respuestas:

140
function doPoll(){
    $.post('ajax/test.html', function(data) {
        alert(data);  // process results here
        setTimeout(doPoll,5000);
    });
}
Johnny Craig
fuente
4
algunas personas han usado setTimeouty otras han usado setInterval. ¿Por qué se preferiría uno a otro?
Mike
36
setinterval haría una llamada ajax cada 5 segundos sin importar qué. la forma en que lo he escrito (que creo que es una buena práctica) esperará los resultados ENTONCES haga otra solicitud ajax 5 segundos más tarde. Hay ocasiones en las que usaría setinterval, pero esta no es una de ellas. no deberíamos hacer ninguna solicitud nueva hasta que obtengamos los resultados de la última solicitud
Johnny Craig
107
Sin embargo, tenga en cuenta que el código sugerido dejará de sondear si falla una sola solicitud. En un escenario típico, probablemente querrá seguir votando de todos modos. No lo tendría setTimeoutdentro del controlador de éxito, sino que encadenaría la llamada ajax con jQuery siempre . Así: $.post('ajax/test.html') .done(function(data) { /* process */ }) .always(function() { setTimeout(doPoll, 5000); });
Mårten Wikström
6
No hay optimización de llamadas de cola. Esto solo seguiría aumentando la pila de llamadas de función. Se recomienda el uso de un patrón de trampolín.
Boopathi Rajaa
8
@BoopathiRajaa, proporcione un ejemplo de dicho patrón de trampolín.
santa
60

Aquí hay un artículo útil sobre el sondeo largo (solicitud HTTP de larga duración) usando jQuery. Un fragmento de código derivado de este artículo:

(function poll() {
    setTimeout(function() {
        $.ajax({
            url: "/server/api/function",
            type: "GET",
            success: function(data) {
                console.log("polling");
            },
            dataType: "json",
            complete: poll,
            timeout: 2000
        })
    }, 5000);
})();

Esto hará la siguiente solicitud solo después de que se haya completado la solicitud ajax.

Una variación de lo anterior que se ejecutará inmediatamente la primera vez que se llame antes de respetar el intervalo de espera / tiempo de espera.

(function poll() {
    $.ajax({
        url: "/server/api/function",
        type: "GET",
        success: function(data) {
            console.log("polling");
        },
        dataType: "json",
        complete: setTimeout(function() {poll()}, 5000),
        timeout: 2000
    })
})();
chrisjleu
fuente
¿Hay alguna forma de cancelar el sondeo o indicarle que se detenga?
Tal
¿Cómo borro el tiempo de espera si se obtiene el resultado esperado del servidor?
abhishek77 el
Puede borrar el tiempo de espera como en este ejemplo:let is_success = false; (function poll() { let timeout = setTimeout(function() { $.ajax({ url: resp.location, type: "GET", success: function(data) { if(YOUR_CONDITION) { is_success=true; } }, dataType: "json", complete: poll, timeout: 2000 }) }, 5000); if(is_success) { console.log("ending poll"); window.clearTimeout(timeout); } })();
Marius
2
No haga clic en el enlace techoctave.com de arriba. Intenta hacer todo tipo de cosas desagradables
Siddharth Ram
13

Desde ES6,

var co = require('co');
var $ = require('jQuery');

// because jquery doesn't support Promises/A+ spec
function ajax(opts) {
  return new Promise(function(resolve, reject) {
    $.extend(opts, {
      success: resolve,
      error: reject
    });
    $.ajax(opts);
  }
}

var poll = function() {
  co(function *() {
    return yield ajax({
      url: '/my-api',
      type: 'json',
      method: 'post'
    });
  }).then(function(response) {
    console.log(response);
  }).catch(function(err) {
    console.log(err);
  });
};

setInterval(poll, 5000);
  • No usa recursividad (la pila de funciones no se ve afectada).
  • No sufre donde setTimeout-recursión necesita ser optimizado para llamadas finales.
Boopathi Rajaa
fuente
¡Es bueno ver una solución ES6!
PHearst
¿Qué lo convierte en una solución ES6 Boopathi Rajaa, setInterval ()?
Halil
11
function poll(){
    $("ajax.php", function(data){
        //do stuff  
    }); 
}

setInterval(function(){ poll(); }, 5000);
génesis
fuente
3
Nota: Puede utilizar esta sintaxissetInterval(poll, 5000);
R3tep
7
function make_call()
{
  // do the request

  setTimeout(function(){ 
    make_call();
  }, 5000);
}

$(document).ready(function() {
  make_call();
});
PeeHaa
fuente
2

jQuery.Deferred () puede simplificar la gestión de la secuenciación asincrónica y el manejo de errores.

polling_active = true // set false to interrupt polling

function initiate_polling()
    {
    $.Deferred().resolve() // optional boilerplate providing the initial 'then()'
    .then( () => $.Deferred( d=>setTimeout(()=>d.resolve(),5000) ) ) // sleep
    .then( () => $.get('/my-api') ) // initiate AJAX
    .then( response =>
        {
        if ( JSON.parse(response).my_result == my_target ) polling_active = false
        if ( ...unhappy... ) return $.Deferred().reject("unhappy") // abort
        if ( polling_active ) initiate_polling() // iterative recursion
        })
    .fail( r => { polling_active=false, alert('failed: '+r) } ) // report errors
    }

Este es un enfoque elegante, pero hay algunas trampas ...

  • Si no desea then()que falle inmediatamente, la devolución de llamada debería devolver otro objeto thenable (probablemente otroDeferred ), lo que hacen las líneas sleep y ajax.
  • Los otros son demasiado embarazosos para admitir. :)
Brent Bradburn
fuente
Respuestas similares en: Diferido en un ciclo
temporal
Mi comentario de "recursividad iterativa" puede ser un poco engañoso. No hay recursividad real aquí, ya que la llamada "recursiva" se produce desde una devolución de llamada anónima, después de que se initiate_pollinghaya completado.
Brent Bradburn
En los navegadores más recientes, ya no necesita jQuery, haga esto; vea mi respuesta aquí: stackoverflow.com/a/48728503/86967
Brent Bradburn
Tiempo de espera de JavaScript puro:new Promise( resolve => setTimeout(resolve,1000) ).then( () => alert("done") )
Brent Bradburn
La recursión asíncrona es iteración
Brent Bradburn
0
(function poll() {
    setTimeout(function() {
        //
        var search = {}
        search["ssn"] = "831-33-6049";
        search["first"] = "Harve";
        search["last"] = "Veum";
        search["gender"] = "M";
        search["street"] = "5017 Ottis Tunnel Apt. 176";
        search["city"] = "Shamrock";
        search["state"] = "OK";
        search["zip"] = "74068";
        search["lat"] = "35.9124";
        search["long"] = "-96.578";
        search["city_pop"] = "111";
        search["job"] = "Higher education careers adviser";
        search["dob"] = "1995-08-14";
        search["acct_num"] = "11220423";
        search["profile"] = "millenials.json";
        search["transnum"] = "9999999";
        search["transdate"] = $("#datepicker").val();
        search["category"] = $("#category").val();
        search["amt"] = $("#amt").val();
        search["row_key"] = "831-33-6049_9999999";



        $.ajax({
            type : "POST",
            headers : {
                contentType : "application/json"
            },
            contentType : "application/json",
            url : "/stream_more",
            data : JSON.stringify(search),
            dataType : 'json',
            complete : poll,
            cache : false,
            timeout : 600000,
            success : function(data) {
                //
                //alert('jax')
                console.log("SUCCESS : ", data);
                //$("#btn-search").prop("disabled", false);
                // $('#feedback').html("");
                for (var i = 0; i < data.length; i++) {
                    //
                    $('#feedback').prepend(
                            '<tr><td>' + data[i].ssn + '</td><td>'
                                    + data[i].transdate + '</td><td>'
                                    + data[i].category + '</td><td>'
                                    + data[i].amt + '</td><td>'
                                    + data[i].purch_prob + '</td><td>'
                                    + data[i].offer + '</td></tr>').html();
                }

            },
            error : function(e) {
                //alert("error" + e);

                var json = "<h4>Ajax Response</h4><pre>" + e.responseText
                        + "</pre>";
                $('#feedback').html(json);

                console.log("ERROR : ", e);
                $("#btn-search").prop("disabled", false);

            }
        });

    }, 3000);
})();
vaquar khan
fuente
0

Esta solución:

  1. tiene tiempo de espera
  2. el sondeo también funciona después de una respuesta de error

La versión mínima de jQuery es 1.12

$(document).ready(function () {
  function poll () {
    $.get({
      url: '/api/stream/',
      success: function (data) {
        console.log(data)
      },
      timeout: 10000                    // == 10 seconds timeout
    }).always(function () {
      setTimeout(poll, 30000)           // == 30 seconds polling period
    })
  }

  // start polling
  poll()
})
jozo
fuente