jQuery, exemple de sondage simple

105

J'apprends jQuery et j'essaie de trouver un exemple de code simple qui interrogera une API pour une condition. (c.-à-d. demander une page Web toutes les quelques secondes et traiter les résultats)

Je suis familier avec la façon de faire AJAX dans jQuery, je n'arrive tout simplement pas à trouver le moyen "approprié" de le faire exécuter sur un "timer".

Mike
la source

Réponses:

140
function doPoll(){
    $.post('ajax/test.html', function(data) {
        alert(data);  // process results here
        setTimeout(doPoll,5000);
    });
}
Johnny Craig
la source
4
certaines personnes ont utilisé setTimeoutet certains ont utilisé setInterval. Pourquoi l'un serait-il préféré à l'autre?
Mike
36
setinterval ferait un appel ajax toutes les 5 secondes quoi qu'il arrive. la façon dont je l'ai écrit (ce que je crois est une bonne pratique) attendra les résultats PUIS faire une autre requête ajax 5 secondes plus tard. il y a des moments où j'utiliserais setinterval, mais ce n'est pas l'un d'entre eux. nous ne devrions pas faire de nouvelles demandes jusqu'à ce que nous obtenions les résultats de la dernière demande
Johnny Craig
107
Attention cependant, le code suggéré arrêtera d'interroger si une seule demande échoue. Dans un scénario typique, vous voudrez probablement continuer à interroger de toute façon. Je n'aurais pas setTimeoutdans le gestionnaire de succès mais enchaînez toujours l'appel ajax avec jQuery . Comme ça: $.post('ajax/test.html') .done(function(data) { /* process */ }) .always(function() { setTimeout(doPoll, 5000); });
Mårten Wikström
6
Il n'y a pas d'optimisation des appels de fin. Cela ne ferait que continuer à augmenter la pile d'appels de fonction. L'utilisation d'un modèle de trampoline est recommandée.
Boopathi Rajaa
8
@BoopathiRajaa veuillez fournir un exemple d'un tel modèle de trampoline.
Santa
60

Voici un article utile sur l'interrogation longue (requête HTTP de longue durée) à l'aide de jQuery. Un extrait de code dérivé de cet article:

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

Cela fera la demande suivante seulement une fois la demande ajax terminée.

Une variante de ce qui précède qui s'exécutera immédiatement la première fois qu'elle sera appelée avant d'honorer l'intervalle d'attente / de temporisation.

(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
la source
Existe-t-il un moyen d'annuler l'interrogation ou de lui signaler son arrêt?
Tal
Comment effacer le délai d'attente si le résultat attendu est obtenu du serveur?
abhishek77 du
Vous pouvez effacer le délai comme dans cet exemple: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
Ne cliquez pas sur le lien techoctave.com ci-dessus. Essaie de faire toutes sortes de choses désagréables
Siddharth Ram
13

Depuis 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);
  • N'utilise pas la récursivité (la pile de fonctions n'est pas affectée).
  • Ne souffre pas là où setTimeout-récursivité doit être optimisé pour les appels de fin.
Boopathi Rajaa
la source
Ravi de voir une solution ES6!
PHearst
Qu'est-ce qui en fait une solution ES6 Boopathi Rajaa, setInterval ()?
Halil
11
function poll(){
    $("ajax.php", function(data){
        //do stuff  
    }); 
}

setInterval(function(){ poll(); }, 5000);
genèse
la source
3
Remarque: vous pouvez utiliser cette syntaxesetInterval(poll, 5000);
R3tep
7
function make_call()
{
  // do the request

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

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

jQuery.Deferred () peut simplifier la gestion du séquençage asynchrone et de la gestion des erreurs.

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
    }

C'est une approche élégante, mais il y a des pièges ...

  • Si vous ne voulez pas que a then()tombe immédiatement, le rappel doit renvoyer un autre objet alors utilisable (probablement un autre Deferred), ce que font les deux lignes sleep et ajax.
  • Les autres sont trop embarrassants pour l'admettre. :)
Brent Bradburn
la source
Réponses similaires à: Différé dans une boucle while
Brent Bradburn
Mon commentaire de "récursivité itérative" peut être un peu trompeur. Il n'y a pas de récursion réelle ici puisque l'appel "récursif" se produit à partir d'un rappel anonyme - après initiate_pollingavoir été exécuté jusqu'à la fin.
Brent Bradburn
Dans les derniers navigateurs, vous n'avez plus besoin de jQuery pour faire cela - voir ma réponse ici: stackoverflow.com/a/48728503/86967
Brent Bradburn
Délai d'expiration purement JavaScript:new Promise( resolve => setTimeout(resolve,1000) ).then( () => alert("done") )
Brent Bradburn
Async Recursion Is 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
la source
0

J'ai créé un petit plugin JQuery pour cela. Vous pouvez l'essayer:

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

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

Sohan
la source
0

Cette solution:

  1. a un délai d'expiration
  2. l'interrogation fonctionne également après une réponse d'erreur

La version minimale de jQuery est 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
la source