Polling implementation using setInterval in knocko

2019-07-27 04:02发布

问题:

I am trying to implement simple polling mechanism using setInterval. I have a Viewmodel as follows:

define([ 'knockout', 'jquery',
    ], function ( ko, $) {
    function ViewModel() {
        var self = this;
        //setInterval( function() {
        $.ajax({url: "", async: false,timeout: 3000, success: function (data) {
           // some operation

            }, dataType: "json"});
      //}, 3000);

    }
    return ViewModel;


 });

Upto this it works fine ajax call return data and does operation.How do I use setInterval so that ajax call returns data after certain interval so that ViewModel is updated and data get refreshed in UI? If I uncomment the setInterval block then ViewModel is not getting returned to the DOM.I think setInterval is asynchronous. Any solutions is appreciated.

回答1:

Basically, using setInterval with async code is not the best way to go. It's better to use setTimeout to schedule a new request once the previous one has finished.

If you make sure there can't be two pending requests at once, you can access your ViewModel instance through self in your success handler and you won't have to worry of older/other requests undoing your change.

Here's an example:

function ViewModel() {
  var self = this;

  var INTERVAL = 5000;
  var timeout = null;
  var currentReq = null;
  
  this.observableProp = ko.observable("empty");

  var fetchNewData = function() {
    currentReq = $.ajax( /* options */);
    
    currentReq
      .done(processNewData)
      .always(scheduleNewDataFetch);
  };

  var processNewData = function(data) {
    // self refers to your current ViewModel instance
    // set observable properties using self.prop(data)
    self.observableProp("data");
  };
  
  var scheduleNewDataFetch = function() {
    if (currentReq) {
      currentReq.abort();  
    }
    
    if (timeout) {
      clearTimeout(timeout);  
    }
    
    currentReq = null;
    timeout = setTimeout(fetchNewData, INTERVAL);
    
  };

  fetchNewData(); // Starts the update loop
}



回答2:

You could try simply doing:

define([ 'knockout', 'jquery',
    ], function ( ko, $) {
    function ViewModel() {
        var self = this;
        var refreshInterval = /* your refresh interval in ms here*/;
        setInterval( function() {
            $.ajax({url: "", async: false, success: function (data) {
                // some operation

                timeout: refreshInterval
                }, dataType: "json"});
        }, refreshInterval);

    }
    return ViewModel;

 });

The ajax call is made every refreshInterval (in ms). The timeout property is a security to be sure the answer you get during one interval are the data of this interval, and not the data from a previously unanswered call that got late.