Reputation: 313
I have a function upload_image that uploads a file from a form and returns a promise representing the ajax request. However, it's possible that the user hasn't selected a file on that form yet, in which case I can't return a promise because there will be no ajax request. However, the code that calls upload_image expects a promise for an ajax request back, so the done() and fail() functions assume the ajax request is done or failed. So the question is what should upload_image return if the precondition of the user having already selected a file fails?
In other words, what is the best practice for handling a failed promise that may have failed for different reasons?
I considered returning a promise that is already failed with a string "Please select a file", and then checking for that in the fail function, but it seems hacky. I also considered splitting up validation and ajax submission into two different functions, but that seems like too much overhead for such a small bit of functionality.
upload_image().done(function(){
// image uploaded succesfully
}).fail(function(jqxhr){
// error uploading OR image was not selected - what's the best way to handle this?
});
// pseudocode
function upload_image() {
if (!user_has_selected_a_file) {
// what to do here? maybe:
// return new $.Deferred().reject('Please select a file');
} else {
return $.ajax();
}
}
Upvotes: 2
Views: 1605
Reputation: 18078
Simplest approach is probably to simulate a jqXHR error, in such a way that the error handler needs only be superficially aware of whether the failure was a genuine jqXHR error or something synthetic.
For example:
function upload_image() {
if (!user_has_selected_a_file) {
return $.Deferred().reject({simulated:true}, 'Please select a file', 'No file selected').promise();
} else {
return $.ajax(...);
}
}
Then, in its simplest form, the response made by upload_image()
could structured as follows :
upload_image().done(function(data, textStatus, jqXHR) {
// image uploaded succesfully
}).fail(function(jqXHR, textStatus, errorThrown) {
//display textStatus and/or errorThrown as required
});
Or, if you need to distinguish positively between the two types of failure :
upload_image().done(function(data, textStatus, jqXHR) {
// image uploaded succesfully
}).fail(function(jqXHR, textStatus, errorThrown) {
if(jqXHR.simulated) {
//display textStatus and/or errorThrown as required
}
else {
//handle the genuine jqXHR and/or display textStatus and/or errorThrown as required.
}
});
Upvotes: 3
Reputation: 119897
You can manually create a Deferred object, fail it immediately with .reject()
or .rejectWith()
and return it from your function. You can optionally pass in arguments to it that would indicate the error.
Any fail callbacks attached to an already failed Deferred object will execute immediately.
Upvotes: 0
Reputation: 276393
Handle it in your fail function. You have return a deffered call for it to be a logical call to .done / .fail
Upvotes: 0