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.

Antworten:


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

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

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.

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

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

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. :) :)


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


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()
})
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.