I've got an existing api routine that I'd like to insert transform before the next .done()
gets called. In my case it a simple extra level of JSON.parse()
that needs to occur but the wider question is can I do anything to the response data that the next .done()
will be able to see?
so take this api :
function foo(){
return $.ajax( ... )
.done(data=> { .. do something with the data here ...});
}
and the caller can see this:
foo().done(data=>{ .. transformed data visible here ... });
jQuery's ajax
returns a Deferred
object, which is (now) a promise per the Promises/A+ specification. So you could switch to using then
, which has the semantics you're looking for:
function foo(){
return $.ajax( ... )
.then(data => {
return /*...the transformed data...*/;
});
}
then:
foo().then(data => { /*.. transformed data visible here ...*/ });
Note: If the code calling foo
can't be changed, no worries; done
will see the updated data, too. But it has to be then
within foo
. Switch to then
in the code calling foo
too if you can, but if you can't, it's fine.
Here's a live example using then
within foo
and done
when calling it: https://jsfiddle.net/tjcrowder/y1zh2xL4/
function foo(){
return $.ajax({
method: "POST",
url: "/echo/json/",
data: {
json: '{"key":"value"}',
delay: 1
}
})
.then(data => {
return {key: data.key.toUpperCase()};
});
}
// Just to show that `done` sees the updated data
foo().done(data => { console.log(data); });
In a comment you asked:
Further question; is there a way to do the same sort of transform in an error chain?
Yup! Promises are designed such that the two paths can be transformed at each level. To transform the rejection passing through the chain, you either return a rejected promise (return Promise.reject(x)
) or throw (throw x
). x
can be anything you want, although by convention it's usually an Error
object.
So for instance (https://jsfiddle.net/tjcrowder/y1zh2xL4/1/):
function foo(){
return $.ajax({
method: "POST",
url: "/echo/bad-url-not-on-jsfiddle",
data: {
json: '{"key":"value"}',
delay: 1
}
})
.then(data => {
return {key: data.key.toUpperCase()};
})
.catch(error => {
const myError = new Error("ajax failed");
myError.originalError = error;
myError.otherInformation = "whatever";
throw myError;
});
}
foo()
.done(data => { console.log(data); })
.fail(error => {
console.error(error);
console.error(error.otherInformation);
});