I'm using Backbone.js and using fetch with options, but it doesn't seem to get the error or success callbacks, however data is being returned.
this.user.fetch({data: {username : this.username.val(), check : 'true'}}, {
error: function(model, response) {
console.log(response);
},
success: function(model, response) {
console.log(response);
}
});
This is what I have setup, am I missing something? It never hits error or success, but it does do the ajax request and it's returning data.
Thank you!
You're passing 2 separate arguments to fetch. Combine them into a single object with data, success, and error fields and it should work for you.
Example for x1a4 answer
var myModel = new MyModel({id: modelId});
myModel.fetch({
success: function (model) {
console.log('success: model fetched');
},
error: function () {
console.log('error: loading model');
}
});
Related
I'm struggling with something - which I'm guessing means I've misunderstood and am doing something silly
I have an observable and need to use it to create some object, send that to the server for processing, combine a result from the server with the object I sent, and then turn that into an observable so what I want to do (I think) is something like
var theNewObservable = my.observable.things.select(function(thing) {
var dataToSend = generateMyJavascriptObjectFrom(thing);
var promise = $.ajax({
type: 'POST',
url: http://somewhere.com,
data: dataToSend
}).promise();
return rx.Observable.fromPromise(promise).subscribe(function(data, status, jqXHR) {
var infoFromServer = jqXHR.getResponseHeader('custom-header-returned');
// I'm wanting this to be the thing other code can subscribe to
return { infoFromServer: dataToSend };
}, function(err) {
alert('PC LOAD LETTER!');
console.error(err);
});
}
});
theNewObservable.subscribe(function(combinedInfo) { console.log(combinedInfo) };
where I'm expecting {infoFromServer: dataToSend} I'm getting an AutoDetachObserver and I can see that has an onNext with the ajax onSuccess signature so I'm obviously doing something silly
A couple things that should help a bit:
1) The subscribe method is a terminal method, as in, it won't return anything. It is where the Observer attaches so there should be no further data propagation after the subscribe
2) The onNext method of subscribe can only take a single value which you will need to have all the message data wrapped in.
Since jQuery's Promise will not behave well with this, you have two options. First, you can use the RX-DOM project for an Observable ajax version. Or you will need to wrap the promise method. If you further need to wait on the response you should be using selectMany instead, which will allow you to fire off the promise, then await its return and map the response to the original request.
var theNewObservable = my.observable.things
//Preprocess this so that `selectMany` will use
//dataToSend as the request object
.map(function(thing) { return generateMyJavascriptObjectFrom(thing); })
.selectMany(function(dataToSend) {
var promise = $.ajax({
type: 'POST',
url: http://somewhere.com,
data: dataToSend
}).promise();
//Rewrap this into a promise that RxJS can handle
return promise.then(function(data, status, jqXHR) {
return {data : data, status : status, jqXHR : jqXHR};
});
}, function(request, response) {
return {
infoFromServer : response.jqXHR.getResponse('custom-header'),
dataToSend : request
};
});
theNewObservable.subscribe(
function(combinedInfo) {
console.log(combinedInfo)
},
function(err) {
alert('PC LOAD LETTER!');
console.error(err);
});
I'm currently dealing with refactoring my code, and trying to automate AJAX requests as follows:
The goal is to have a context-independent function to launch AJAX requests. The data gathered is handled differently based on the context.
This is my function:
function ajaxParameter(routeName, method, array, callback){
//Ajax request on silex route
var URL = routeName;
$.ajax({
type: method,
url: URL,
beforeSend: function(){
DOM.spinner.fadeIn('fast');
},
})
.done(function(response) {
DOM.spinner.fadeOut('fast');
callback(response);
})
.fail(function(error){
var response = [];
response.status = 0;
response.message = "Request failed, error : "+error;
callback(response);
})
}
My problem essentially comes from the fact that my callback function is not defined.
I would like to call the function as such (example)
ajaxParameter(URL_base, 'POST', dataBase, function(response){
if(response.status == 1 ){
console.log('Request succeeded');
}
showMessage(response);
});
I thought of returning response to a variable and deal with it later, but if the request fails or is slow, this won't work (because response will not have been set).
That version would allow me to benefit the .done() and .fail().
EDIT : So there is no mistake, I changed my code a bit. The goal is to be able to deal with a callback function used in both .done() and .fail() context (two separate functions would also work in my case though).
As far as I can see there really is nothing wrong with your script. I've neatened it up a bit here, but it's essentially what you had before:
function ajaxParameter (url, method, data, callback) {
$.ajax({
type: method,
url: url,
data: data,
beforeSend: function(){
DOM.spinner.fadeIn('fast');
}
})
.done( function (response) {
DOM.spinner.fadeOut('fast');
if (callback)
callback(response);
})
.fail( function (error){
var response = [];
response.status = 0;
response.message = "Request failed, error : " + error;
if (callback)
callback(response);
});
}
And now let's go and test it here on JSFiddle.
As you can see (using the JSFiddle AJAX API), it works. So the issue is probably with something else in your script. Are you sure the script you've posted here is the same one you are using in your development environment?
In regards to your error; be absolutely sure that you are passing in the right arguments in the right order to your ajaxParameter function. Here's what I am passing in the fiddle:
the url endpoint (e.g http://example.com/)
the method (e.g 'post')
some data (e.g {foo:'bar'})
the callback (e.g function(response){ };)
Do you mean something like this, passing the success and fail callbacks:
function ajaxParameter(routeName, method, array, success, failure) {
//Ajax request on silex route
var URL = routeName;
$.ajax({
type: method,
url: URL,
beforeSend: function () {
DOM.spinner.fadeIn('fast');
}
}).done(function (response) {
DOM.spinner.fadeOut('fast');
success(response);
}).fail(function (error) {
var response = [];
response.status = 0;
response.message = "Request failed, error : " + error;
failure(response);
})
}
Called like:
ajaxParameter(
URL_base,
'POST',
dataBase,
function(response){
//success function
},
function(response){
// fail function
}
);
So when handling, for example, the success data in jquery, should you check if the return data has the necessary data like this:
success: function (data) {
if (data.new_rank !== undefined) {
$('._user_rank').html(data.new_rank);
}
}
Or let it fail when it is not present?
success: function (data) {
$('._user_rank').html(data.new_rank);
}
in the previous example you can check if something has changed and needs to be fixt because of the error.
What approach is the best?
It's better you check it, for other code that may be you have in complete or other event. If you didn't, they will not run after error. You can check it this too:
success: function (data) {
if (data.new_rank) {
$('._user_rank').html(data.new_rank);
}
}
jQuery ajax requests provide you a way to handle request errors.
$.ajax(url, {
success: function(data) {
// success
},
error: function() {
// error
}
});
If it's not a request error that you are trying to catch you still should handle error by yourself and not let javascript throw them all the way.
One solution I would say is follow strict data type in $.ajax like dataType: json.
Use success and error handler. And if the return data is anything other than json type it will be handled through error handler.
$.ajax(url, {
dataType: 'json'
success: function(data) {
// success
},
error: function() {
// error
}
});
The Backbone model
define('PreferedDealerAddress.Model', function (){
'use strict';
return Backbone.Model.extend( {
urlRoot: '/c.3927030/mazda-mstore-checkout-1-0/service/PreferedDealerAddress.ss'
} );
});
The back bone collection
define('PreferedDealerAddress.Collection', ['PreferedDealerAddress.Model'], function (Model)
{
'use strict';
return Backbone.Collection.extend(
{
model: Model
, url: '../mazda-mstore-checkout-1-0/service/PreferedDealerAddress.ss'
, initialize: function(){
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
},
fetchSuccess: function (collection, response) {
console.log('Collection fetch success', response);
console.log('Collection models: ', collection.models);
},
fetchError: function (collection, xhr, options) {
console.log(xhr.responseText);
throw new Error("Books fetch error");
}
} );
});
Now In router I am creating the back bone collection and calling the fetch function by passing the parameter/query string like belwo
var search_params = {
'zip': zip
};
new PreferedDealerAddress.Collection().fetch({data: $.param(search_params)});
But it is making two AJAX call the first one is
/mazda-mstore-checkout-1-0/service/PreferedDealerAddress.ss
/mazda-mstore-checkout-1-0/service/PreferedDealerAddress.ss?zip=92618
and the fetch method considering the first AJAX call which is returning a blank JSON array , due to missing query parameter.
The below is screenshot from firebug.
Please help me, I can use $.getJson() and initialize the collection but that is not the proper way.
That's actually quite simple. Your first fetch is in the initialize method - the one without the data param:
, initialize: function(){
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
},
Then your second request is when you instantiate the Collection with the data param included.
So you just need to get rid of the fetch in the initialization.
I have a model.save, it works fine.
this.model.save({
success: function (model, response) {
alert('hello');
},
error: function (model, xhr, options) {
alert('hello');
},
});
The controller is sending back 500, which i want it to right now for testing.
$response = [
'status' => 'error',
'message' => 'Cannot delete! Image is in use.'
];
return Response::json($response, 500);
console.log shows: POST /mysite/public/api/test 500 (Internal Server Error)
It is not alerting me 'hello', so for some reason my error callback function is not working. I can't find any problems with the syntax. Anyone else spot my problem? If so thank you!
The first argument of the save method is a set of attributes to save, and the second argument is the the options hash which should contain your callbacks. Modify your call to look like this:
this.model.save(null, {
success: function (model, response) {
console.log("success");
},
error: function (model, response) {
console.log("error");
}
});