JavaScript Promises: chaining promises with non-promise objects. Why it works?











up vote
2
down vote

favorite
1












I'm learning about JavaScript Fetch API and I'm a bit confusing about Promises.



Consider this dummy example that prints "ok" in the console:



fetch(".")
.then(function(response) { // first then() call
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


The page about the Response Object of the Fetch API says:




The fetch() call returns a promise, which resolves with the Response
object associated with the resource fetch operation.




Well, since fetch() returns a Promise object I can understand that the first then() call works fine because a Promise object has this method. But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!



Altering the dummy example prints undefined in the first console.log():



fetch(".")
.then(function(response) { // first then() call
console.log(response.then)
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


My questions is: Why this works? How the second call to then() works since the returned object does not have this method? Is it a kind of syntax sugar?



Thanks!










share|improve this question




















  • 2




    "How the second call to then() works since the returned object does not have this method?" - The .then() function calls themselves occur immediately and each return a promise object, they're not dependent on the previous callback in the chain returning something with a .then() method.
    – nnnnnn
    May 17 '17 at 2:45












  • To support @nnnnnn, here: stackoverflow.com/a/27716518/4279440 is a good explanation of this behavior.
    – Travis Clarke
    May 17 '17 at 2:49

















up vote
2
down vote

favorite
1












I'm learning about JavaScript Fetch API and I'm a bit confusing about Promises.



Consider this dummy example that prints "ok" in the console:



fetch(".")
.then(function(response) { // first then() call
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


The page about the Response Object of the Fetch API says:




The fetch() call returns a promise, which resolves with the Response
object associated with the resource fetch operation.




Well, since fetch() returns a Promise object I can understand that the first then() call works fine because a Promise object has this method. But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!



Altering the dummy example prints undefined in the first console.log():



fetch(".")
.then(function(response) { // first then() call
console.log(response.then)
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


My questions is: Why this works? How the second call to then() works since the returned object does not have this method? Is it a kind of syntax sugar?



Thanks!










share|improve this question




















  • 2




    "How the second call to then() works since the returned object does not have this method?" - The .then() function calls themselves occur immediately and each return a promise object, they're not dependent on the previous callback in the chain returning something with a .then() method.
    – nnnnnn
    May 17 '17 at 2:45












  • To support @nnnnnn, here: stackoverflow.com/a/27716518/4279440 is a good explanation of this behavior.
    – Travis Clarke
    May 17 '17 at 2:49















up vote
2
down vote

favorite
1









up vote
2
down vote

favorite
1






1





I'm learning about JavaScript Fetch API and I'm a bit confusing about Promises.



Consider this dummy example that prints "ok" in the console:



fetch(".")
.then(function(response) { // first then() call
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


The page about the Response Object of the Fetch API says:




The fetch() call returns a promise, which resolves with the Response
object associated with the resource fetch operation.




Well, since fetch() returns a Promise object I can understand that the first then() call works fine because a Promise object has this method. But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!



Altering the dummy example prints undefined in the first console.log():



fetch(".")
.then(function(response) { // first then() call
console.log(response.then)
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


My questions is: Why this works? How the second call to then() works since the returned object does not have this method? Is it a kind of syntax sugar?



Thanks!










share|improve this question















I'm learning about JavaScript Fetch API and I'm a bit confusing about Promises.



Consider this dummy example that prints "ok" in the console:



fetch(".")
.then(function(response) { // first then() call
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


The page about the Response Object of the Fetch API says:




The fetch() call returns a promise, which resolves with the Response
object associated with the resource fetch operation.




Well, since fetch() returns a Promise object I can understand that the first then() call works fine because a Promise object has this method. But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!



Altering the dummy example prints undefined in the first console.log():



fetch(".")
.then(function(response) { // first then() call
console.log(response.then)
return response;
}).then(function(response) { // second then() call
console.log("ok");
});


My questions is: Why this works? How the second call to then() works since the returned object does not have this method? Is it a kind of syntax sugar?



Thanks!







javascript promise es6-promise






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 18 '17 at 13:39

























asked May 17 '17 at 2:40









Bruno Peres

11.5k32553




11.5k32553








  • 2




    "How the second call to then() works since the returned object does not have this method?" - The .then() function calls themselves occur immediately and each return a promise object, they're not dependent on the previous callback in the chain returning something with a .then() method.
    – nnnnnn
    May 17 '17 at 2:45












  • To support @nnnnnn, here: stackoverflow.com/a/27716518/4279440 is a good explanation of this behavior.
    – Travis Clarke
    May 17 '17 at 2:49
















  • 2




    "How the second call to then() works since the returned object does not have this method?" - The .then() function calls themselves occur immediately and each return a promise object, they're not dependent on the previous callback in the chain returning something with a .then() method.
    – nnnnnn
    May 17 '17 at 2:45












  • To support @nnnnnn, here: stackoverflow.com/a/27716518/4279440 is a good explanation of this behavior.
    – Travis Clarke
    May 17 '17 at 2:49










2




2




"How the second call to then() works since the returned object does not have this method?" - The .then() function calls themselves occur immediately and each return a promise object, they're not dependent on the previous callback in the chain returning something with a .then() method.
– nnnnnn
May 17 '17 at 2:45






"How the second call to then() works since the returned object does not have this method?" - The .then() function calls themselves occur immediately and each return a promise object, they're not dependent on the previous callback in the chain returning something with a .then() method.
– nnnnnn
May 17 '17 at 2:45














To support @nnnnnn, here: stackoverflow.com/a/27716518/4279440 is a good explanation of this behavior.
– Travis Clarke
May 17 '17 at 2:49






To support @nnnnnn, here: stackoverflow.com/a/27716518/4279440 is a good explanation of this behavior.
– Travis Clarke
May 17 '17 at 2:49














1 Answer
1






active

oldest

votes

















up vote
8
down vote



accepted











But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!




Yes, because the second .then() invocation is on the return value of the first then call, not on the response. The promise then method always returns a promise - which makes it chainable. It does not return the return value of the asynchronous callback - for that it would need to peek into the future.



Look closely:



const promise1 = fetch(".");
const promise2 = promise1.then(function(response) { // first then() call
return response;
});
const promise3 = promise2.then(function(response) { // second then() call
console.log("ok");
});


It's not



fetch(".").then(function(response) { // outer then() call
return response.then(function() { // inner then() call
console.log("ok");
});
});


which indeed doesn't work without response being a promise.






share|improve this answer



















  • 2




    Great answer! Thanks! :)
    – Bruno Peres
    May 18 '17 at 14:27











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44014605%2fjavascript-promises-chaining-promises-with-non-promise-objects-why-it-works%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
8
down vote



accepted











But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!




Yes, because the second .then() invocation is on the return value of the first then call, not on the response. The promise then method always returns a promise - which makes it chainable. It does not return the return value of the asynchronous callback - for that it would need to peek into the future.



Look closely:



const promise1 = fetch(".");
const promise2 = promise1.then(function(response) { // first then() call
return response;
});
const promise3 = promise2.then(function(response) { // second then() call
console.log("ok");
});


It's not



fetch(".").then(function(response) { // outer then() call
return response.then(function() { // inner then() call
console.log("ok");
});
});


which indeed doesn't work without response being a promise.






share|improve this answer



















  • 2




    Great answer! Thanks! :)
    – Bruno Peres
    May 18 '17 at 14:27















up vote
8
down vote



accepted











But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!




Yes, because the second .then() invocation is on the return value of the first then call, not on the response. The promise then method always returns a promise - which makes it chainable. It does not return the return value of the asynchronous callback - for that it would need to peek into the future.



Look closely:



const promise1 = fetch(".");
const promise2 = promise1.then(function(response) { // first then() call
return response;
});
const promise3 = promise2.then(function(response) { // second then() call
console.log("ok");
});


It's not



fetch(".").then(function(response) { // outer then() call
return response.then(function() { // inner then() call
console.log("ok");
});
});


which indeed doesn't work without response being a promise.






share|improve this answer



















  • 2




    Great answer! Thanks! :)
    – Bruno Peres
    May 18 '17 at 14:27













up vote
8
down vote



accepted







up vote
8
down vote



accepted







But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!




Yes, because the second .then() invocation is on the return value of the first then call, not on the response. The promise then method always returns a promise - which makes it chainable. It does not return the return value of the asynchronous callback - for that it would need to peek into the future.



Look closely:



const promise1 = fetch(".");
const promise2 = promise1.then(function(response) { // first then() call
return response;
});
const promise3 = promise2.then(function(response) { // second then() call
console.log("ok");
});


It's not



fetch(".").then(function(response) { // outer then() call
return response.then(function() { // inner then() call
console.log("ok");
});
});


which indeed doesn't work without response being a promise.






share|improve this answer















But the Response object returned in the chained call is not a Promise object. However the second call to then() method works!




Yes, because the second .then() invocation is on the return value of the first then call, not on the response. The promise then method always returns a promise - which makes it chainable. It does not return the return value of the asynchronous callback - for that it would need to peek into the future.



Look closely:



const promise1 = fetch(".");
const promise2 = promise1.then(function(response) { // first then() call
return response;
});
const promise3 = promise2.then(function(response) { // second then() call
console.log("ok");
});


It's not



fetch(".").then(function(response) { // outer then() call
return response.then(function() { // inner then() call
console.log("ok");
});
});


which indeed doesn't work without response being a promise.







share|improve this answer














share|improve this answer



share|improve this answer








edited May 23 '17 at 11:54









Community

11




11










answered May 17 '17 at 2:50









Bergi

359k55533852




359k55533852








  • 2




    Great answer! Thanks! :)
    – Bruno Peres
    May 18 '17 at 14:27














  • 2




    Great answer! Thanks! :)
    – Bruno Peres
    May 18 '17 at 14:27








2




2




Great answer! Thanks! :)
– Bruno Peres
May 18 '17 at 14:27




Great answer! Thanks! :)
– Bruno Peres
May 18 '17 at 14:27


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44014605%2fjavascript-promises-chaining-promises-with-non-promise-objects-why-it-works%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?