getData
doesn't (and can't) return the data or "failed"
; it returns a promise. You consume that promise much the way you did inside getData
:
$(document).ready(function(){
$('.btn').click(function(){
getData().done(function(apiData) { // **
console.log(apiData); // **
}); // **
});
});
In that callback, apiData
will be whatever your callback in getData
returned, so it'll be the data object or the string "failed"
.
(I've used done
there because it's what you used elsewhere, but normally I'd use then
, the standard promise function.)
One of the key things to understand about promises is that then
(and done
) returns a new promise (technically, with real promises, a thenable) that will be settled based on what the callback does.
So consider (let's stick with jQuery's Deferred for now):
function doSomething() {
var d = $.Deferred();
setTimeout(function() {
// Resolve our promise with "a"
d.resolve("a");
}, 10);
return d.promise();
}
// Consume the promise and put it through a chain:
doSomething()
.then(function(result) {
// This callback happens to do synchronous processing
console.log("First callback got", result);
return result.toUpperCase();
})
.then(function(result) {
// This one does something async, and so it returns a promise
var cd = $.Deferred();
setTimeout(function() {
console.log("Second callback got", result);
cd.resolve(result + result);
}, 10);
return cd.promise();
})
.then(function(result) {
console.log("Third callback got", result);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
The output of that is
First callback got a
Second callback got A
Third callback got AA
Now, earlier I said then
always returns a promise (thenable). How does it do that when my first callback is synchronous and returns a value directly, but my second one is async and returns a promise? The then
function looks at the return value from the callback and, if it's "thenable" (something with then
on it), returns it; if it's not thenable, it creates a new, resolved promise with the value as the resolution value.
Just for completeness, here's the example above with native JavaScript promises (requires browser support):
function doSomething() {
return new Promise(function(resolve) {
setTimeout(function() {
// Resolve our promise with "a"
resolve("a");
}, 10);
});
}
// Consume the promise and put it through a chain:
doSomething()
.then(function(result) {
// This callback happens to do synchronous processing
console.log("First callback got", result);
return result.toUpperCase();
})
.then(function(result) {
// This one does something async, and so it returns a promise
return new Promise(function(resolve) {
setTimeout(function() {
console.log("Second callback got", result);
resolve(result + result);
}, 10);
});
})
.then(function(result) {
console.log("Third callback got", result);
});
The output of that is
First callback got a
Second callback got A
Third callback got AA