jQuery, semplice esempio di polling


105

Sto imparando jQuery e sto cercando di trovare un semplice esempio di codice che interroghi un'API per una condizione. (cioè, richiedi una pagina web ogni pochi secondi ed elabori i risultati)

Ho familiarità con come eseguire AJAX in jQuery, non riesco proprio a trovare il modo "corretto" per farlo eseguire su un "timer".

Risposte:


140
function doPoll(){
    $.post('ajax/test.html', function(data) {
        alert(data);  // process results here
        setTimeout(doPoll,5000);
    });
}

4
alcune persone hanno usato setTimeoute altri hanno usato setInterval. Perché uno dovrebbe essere preferito a un altro?
Mike

36
setinterval farebbe una chiamata ajax ogni 5 secondi, non importa cosa. il modo in cui l'ho scritto (che credo sia una buona pratica) aspetterà i risultati QUINDI farà un'altra richiesta ajax 5 secondi dopo. ci sono volte in cui vorrei usare setinterval, ma questo non è uno di questi. non dovremmo fare nuove richieste finché non avremo ottenuto i risultati dell'ultima richiesta
Johnny Craig

107
Attenzione però che il codice suggerito interromperà il polling se una singola richiesta fallisce. In uno scenario tipico, probabilmente vorresti continuare comunque il polling. Non avrei setTimeoutnel gestore di successo ma invece concatenare sempre la chiamata ajax con jQuery . In questo modo: $.post('ajax/test.html') .done(function(data) { /* process */ }) .always(function() { setTimeout(doPoll, 5000); });
Mårten Wikström

6
Non esiste un'ottimizzazione delle chiamate di coda. Ciò continuerebbe ad aumentare lo stack di chiamate di funzione. Si consiglia di utilizzare il modello trampolino.
Boopathi Rajaa

8
@BoopathiRajaa per favore fornisci un esempio di tale modello di trampolino.
santa

60

Ecco un articolo utile sul polling lungo (richiesta HTTP di lunga durata) utilizzando jQuery. Uno snippet di codice derivato da questo articolo:

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

Questo farà la richiesta successiva solo dopo che la richiesta ajax è stata completata.

Una variazione di quanto sopra che verrà eseguita immediatamente la prima volta che viene chiamata prima di rispettare l'intervallo di attesa / timeout.

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

C'è un modo per annullare il polling o segnalarlo di interrompere?
Tal

Come si cancella il timeout se si ottiene il risultato previsto dal server?
abhishek77 il

Puoi cancellare il timeout come in questo esempio: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
Non fare clic sul collegamento techoctave.com sopra. Cerca di fare ogni genere di cose brutte
Siddharth Ram,

13

Da 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);
  • Non usa la ricorsione (lo stack delle funzioni non è interessato).
  • Non soffre dove setTimeout-recursion deve essere ottimizzato per la chiamata in coda.

Bello vedere una soluzione ES6!
Il

Cosa lo rende una soluzione ES6 Boopathi Rajaa, setInterval ()?
Halil

11
function poll(){
    $("ajax.php", function(data){
        //do stuff  
    }); 
}

setInterval(function(){ poll(); }, 5000);

3
Nota: è possibile utilizzare questa sintassisetInterval(poll, 5000);
R3tep

7
function make_call()
{
  // do the request

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

$(document).ready(function() {
  make_call();
});

2

jQuery.Deferred () può semplificare la gestione del sequenziamento asincrono e la gestione degli errori.

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
    }

Questo è un approccio elegante, ma ci sono alcuni trucchi ...

  • Se non vuoi che un falliscathen() immediatamente, il callback dovrebbe restituire un altro oggetto quindi disponibile (probabilmente un altroDeferred ), cosa che fanno entrambe le linee sleep e ajax.
  • Gli altri sono troppo imbarazzanti per ammetterlo. :)


Il mio commento sulla "ricorsione iterativa" potrebbe essere un po 'fuorviante. Non c'è alcuna ricorsione effettiva qui poiché la chiamata "ricorsiva" si verifica da una richiamata anonima - dopo che initiate_pollingè stata eseguita fino al completamento.
Brent Bradburn

Negli ultimi browser, non hai più bisogno di jQuery per farlo - vedi la mia risposta qui: stackoverflow.com/a/48728503/86967
Brent Bradburn

Timeout JavaScript puro:new Promise( resolve => setTimeout(resolve,1000) ).then( () => alert("done") )
Brent Bradburn

La ricorsione asincrona è iterazione
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);
})();


0

Questa soluzione:

  1. ha timeout
  2. il polling funziona anche dopo la risposta all'errore

La versione minima di jQuery è 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()
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.