jQuery, einfaches Polling-Beispiel

105

Ich lerne jQuery und versuche, ein einfaches Codebeispiel zu finden, das eine API nach einer Bedingung abfragt. (dh alle paar Sekunden eine Webseite anfordern und die Ergebnisse verarbeiten)

Ich bin mit der Ausführung von AJAX in jQuery vertraut. Ich kann einfach nicht den "richtigen" Weg finden, um es auf einem "Timer" auszuführen.

Mike
quelle

Antworten:

140
function doPoll(){
    $.post('ajax/test.html', function(data) {
        alert(data);  // process results here
        setTimeout(doPoll,5000);
    });
}
Johnny Craig
quelle
4
Einige Leute haben verwendet setTimeoutund einige haben verwendet setInterval. Warum sollte einer dem anderen vorgezogen werden?
Mike
36
setinterval würde alle 5 Sekunden einen Ajax-Aufruf tätigen, egal was passiert. Die Art und Weise, wie ich es geschrieben habe (was ich für eine gute Praxis halte), wird auf die Ergebnisse warten, DANN 5 Sekunden später eine weitere Ajax-Anfrage stellen. Es gibt Zeiten, in denen ich setinterval verwenden würde, aber dies ist keine davon. Wir sollten keine neuen Anfragen stellen, bis wir die Ergebnisse der letzten Anfrage erhalten
Johnny Craig
107
Bitte beachten Sie jedoch, dass der vorgeschlagene Code die Abfrage beendet, wenn eine einzelne Anforderung fehlschlägt. In einem typischen Szenario möchten Sie wahrscheinlich trotzdem weiter abfragen. Ich hätte nicht setTimeoutim Success-Handler, sondern verkette den Ajax-Aufruf immer mit jQuery . So: $.post('ajax/test.html') .done(function(data) { /* process */ }) .always(function() { setTimeout(doPoll, 5000); });
Mårten Wikström
6
Es gibt keine Tail-Call-Optimierung. Dies würde nur den Funktionsaufrufstapel weiter erhöhen. Die Verwendung eines Trampolinmusters wird empfohlen.
Boopathi Rajaa
8
@BoopathiRajaa bitte geben Sie ein Beispiel für ein solches Trampolinmuster.
Santa
60

Hier ist ein hilfreicher Artikel über lange Abfragen (lang gehaltene HTTP-Anforderung) mit jQuery. Ein aus diesem Artikel abgeleitetes Code-Snippet:

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

Dadurch wird die nächste Anforderung erst nach Abschluss der Ajax-Anforderung gestellt.

Eine Variation der oben genannten Option, die beim ersten Aufruf sofort ausgeführt wird, bevor das Warte- / Timeout-Intervall eingehalten wird.

(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
quelle
Gibt es eine Möglichkeit, die Abfrage abzubrechen oder zu signalisieren, dass sie gestoppt werden soll?
Tal
Wie lösche ich das Zeitlimit, wenn das erwartete Ergebnis vom Server erhalten wird?
Abhishek77in
Sie können das Zeitlimit wie in diesem Beispiel löschen: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
Klicken Sie oben nicht auf den Link techoctave.com. Versucht alle möglichen bösen Dinge zu tun
Siddharth Ram
13

Von 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);
  • Verwendet keine Rekursion (Funktionsstapel ist nicht betroffen).
  • Leidet nicht, wenn setTimeout-Rekursion Tail-Call-optimiert werden muss.
Boopathi Rajaa
quelle
Schön, eine ES6-Lösung zu sehen!
PHearst
Was macht es zu einer ES6-Lösung? Boopathi Rajaa, setInterval ()?
Halil
11
function poll(){
    $("ajax.php", function(data){
        //do stuff  
    }); 
}

setInterval(function(){ poll(); }, 5000);
Genesis
quelle
3
Hinweis: Sie können diese Syntax verwendensetInterval(poll, 5000);
R3tep
7
function make_call()
{
  // do the request

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

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

jQuery.Deferred () kann die Verwaltung der asynchronen Sequenzierung und Fehlerbehandlung vereinfachen.

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
    }

Dies ist ein eleganter Ansatz, aber es gibt einige Fallstricke ...

  • Wenn Sie nicht möchten, dass ein Objekt then()sofort durchfällt , sollte der Rückruf ein anderes dann verwendbares Objekt (wahrscheinlich ein anderes Deferred) zurückgeben, was sowohl die Schlaf- als auch die Ajax-Zeile tun.
  • Die anderen sind zu peinlich, um es zuzugeben. :) :)
Brent Bradburn
quelle
Ähnliche Antworten bei: Aufgeschoben in einer Weile Schleife
Brent Bradburn
Mein Kommentar zur "iterativen Rekursion" könnte etwas irreführend sein. Hier gibt es keine tatsächliche Rekursion, da der "rekursive" Aufruf von einem anonymen Rückruf ausgeht - nachdem initiate_pollinger vollständig ausgeführt wurde.
Brent Bradburn
In den neuesten Browsern muss jQuery dies nicht mehr tun - siehe meine Antwort hier: stackoverflow.com/a/48728503/86967
Brent Bradburn
Pure JavaScript Timeout:new Promise( resolve => setTimeout(resolve,1000) ).then( () => alert("done") )
Brent Bradburn
Async Rekursion ist Iteration
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
quelle
0

Ich habe dafür ein kleines JQuery-Plugin erstellt. Sie können es versuchen:

$.poll('http://my/url', 100, (xhr, status, data) => {
    return data.hello === 'world';
})

https://www.npmjs.com/package/jquerypoll

Sohan
quelle
0

Diese Lösung:

  1. hat eine Zeitüberschreitung
  2. Polling funktioniert auch nach Fehlerantwort

Die Mindestversion von jQuery ist 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
quelle