3/28/2014

[ExtJS] Cancel Duplicate Store Loading Request Automatically

In the previous article, we mentioned how to abort a store request manually. It's used when programmer want to cancel a store loading request manually.


"Refresh" button in grid

Image there's a "Refresh" button in your grid, the user may press the button quickly multiple times. This behavior make store send multiple requests at a short period of time. So it's better to abort the previous requests for performance and data correctness issue.


Cancel Duplicate Store Loading Request Automatically

The following code overrides ExtJS store behavior, making all of stores in web application abort duplicated store loading request automatically. Just put it to somewhere your application initialized.

Ext JS 4.1.1a:

Ext.define('Tonytuan.data.Store', {
  override: 'Ext.data.Store',
  abort: function () {
    var me = this;
    if (me.loading && me.lastOperation) {
      var requests = Ext.Ajax.requests;
      for (id in requests) {
        if (requests.hasOwnProperty(id) && requests[id].options == me.lastOperation.request) {
          Ext.Ajax.abort(requests[id]);
          delete requests[id];
          break;
        }
      }
    }
  },
  constructor: function (config) {
    var me = this;
    me.callParent([config]);
    me.on({
      'beforeload': function (store, operation) {
        // Abort previous request if it has not been completed.
        if (me.loading) {
          me.abort();
        }
        store.lastOperation = operation;
      }
    });
  }
});

Ext JS 5.0.1:

Ext.define('Ext.enhance.data.Store', {
  override: 'Ext.data.Store',
  abort: function() {
    var me = this;
    if (me.isLoading() && me.lastOperation) {
      var requests = Ext.Ajax.requests;
      for (id in requests) {
        if (requests.hasOwnProperty(id) && requests[id].options.url == me.lastOperation.request._url) {
          Ext.Ajax.abort(requests[id]);
          delete requests[id];
          break;
        }
      }
    }
  },
  constructor: function(config) {
    var me = this;
    me.callParent([config]);
    me.on({
      'beforeload': function(store, operation) {
        // abort previous request
        if (me.isLoading()) {
          me.abort();        }
        store.lastOperation = operation;
      }
    });
  }
});