I want to know how to abort a request.
For example, I issue App.MyModel.find()
and later i want to cancel/abort it before it returns from server. I would expect something like this:
var res = App.MyModel.find(); //request sent to server
res.abort(); // abort the request before completion
but this doesn't work - the returned object is a promise
and there is neither abort
nor cancel
methods.
I'm looking for how to call the abort
method on the underlying XMLHttpRequest
object.
Http is request-response interaction.Once the request is sent,it can't be canceled.You can fine some way to ignore the response from the server instead;
I believe, when you call App.MyModel.find()
, it's going to return you a RecordArray
, not a promise
.
From looking at the ember-data source code for RESTAdapter, I don't think there's a way to call abort on your XMLHttpRequest
object.
You can implement your own RESTAdapter:
var myRESTAdapter = DS.Adapter.create({
find: function (store, type, id) {
var req = $.ajax({
url: type.url,
dataType: 'jsonp',
context: store,
success: function(response){
this.load(type, id, response.data);
}
});
req.abort();
},
findAll: function(store, type) {
var req = $.ajax({
url: type.url,
dataType: 'jsonp',
context: store,
success: function(response){
this.loadMany(type, response.data);
}
});
req.abort();
}
});
and call abort in XMLHttpRequest
object.
For those of you that wonder how to do it, here is how I acheived to cancel a jquery ajax request.
First, I defined a new method in my Application store that will call cancelQuery on my custom RESTAdapter.
App.Store = DS.Store.extend({
cancelQuery: function(type){
var adapter = this.adapterFor(this.modelFor(type).modelName);
if(typeof adapter.cancelQuery === 'function'){
adapter.cancelQuery();
}
}
});
In my custom RESTAdapter, I define that new function and override ajaxOptions like this :
App.YOURMODELAdapter = DS.RESTAdapter.extend({
jqXHRs: [],
ajaxOptions: function(url, type, hash) {
// Get default AjaxOptions
var ajaxOptions = this._super(url, type, hash);
// If the function was defined in the DS.RESTAdapter object,
// we must call it in out new beforeSend hook.
var defaultBeforeSend = function(){};
if(typeof ajaxOptions.beforeSend === 'function'){
defaultBeforeSend = ajaxOptions.beforeSend;
}
ajaxOptions.beforeSend = function(jqXHR, settings){
defaultBeforeSend(jqXHR, settings);
this.jqXHRs.push(jqXHR); // Keep the jqXHR somewhere.
var lastInsertIndex = this.jqXHRs.length - 1;
jqXHR.always(function(){
// Destroy the jqXHRs because the call is finished and
// we don't need it anymore.
this.jqXHRs.splice(lastInsertIndex,1);
});
};
return ajaxOptions;
},
// The function we call from the store.
cancelQuery: function(){
for(var i = 0; i < this.jqXHRs.length; i++){
this.jqXHRs[i].abort();
}
}
});
Now, you can just call cancelQuery
in the context of a controller.
this.store.cancelQuery('yourmodel');