Reputation: 107
I started working on an android app. I am at the point that i need to use an API to get some info. I am using an API for movies so it contains id, title and some other info. My problem is that in this URL i don't hav every information that i need so i have to make another fetch for every movie to get the additional info but as i noticed first JS runs the code in the first fetch ( without the nested fetch ) and then it runs the nested fetch. This way some info are not displayed on the screen.
fetch(movie)
.then(function(response) { return response.json(); })
.then(function(responseObject) {
movies.value = responseObject;
for(var i=0;i<movies.value.results.length;i++)
{
movies.value.results[i].poster_path = poster+movies.value.results[i].poster_path;
var info = "http://api.themoviedb.org/3/movie/"+movies.value.results[i].id+"?api_key";
fetch(info)
.then(function(response) { return response.json(); })
.then(function(responseObject) {
moreInfo.value = responseObject;
if(j < movies.value.results.length)
{
movies.value.results[j].runtime = moreInfo.value.runtime;
console.log("print 1 "+movies.value.results[j]);
j++;
}
});
console.log("print 2 "+movies.value.results);
}
});
what i am trying to do here is add from the second fetch the runtime to my movies Observable object. A sortened version of the result :
print 2 : movies.value.results
print 1 : movies.value.results[i]
The problem as i said is that the code inside the first fetch is executed without executing the nested fetch and then the nested fetch executes. Sorry if i did something really bad but i just started developing on android so please show me mercy :D
*Sorry for not explaining about my j variable. It is defined as zero above fetch(movie). The only reason i use it is because i inside fetch(info) is always at the max number i cang get from movie.value.results.length and because i need to pass the runtime at the specific movie.value.result[j]. So i have a counter that increases only when the fetch(info) is executed.
Upvotes: 1
Views: 5040
Reputation: 4066
This snippet might have some other problems too, like pointed out in the comments, but I think I know where the main confusion comes here.
The problem as i said is that the code inside the first fetch is executed without executing the nested fetch and then the nested fetch executes.
This is not true. Or, at least the order of console logs doesn't imply that. The order of execution inside the outer then-callback is
fetch(info)
This statement starts fetching the data.then(function(response){ ... })
Register a callback to execute when the promise gets resolved. Note that as fetching is asynchronous, the callback function does not get called right away. It will get called later, when the data has finished loading. Meanwhile, synchronous execution of the call stack continues..then(function(responseObject) { ... })
Same thing here. We create a function to run when the data is ready (if ever). Meanwhile the statements outside that function can still be evaluated.console.log("print 2 "+movies.value.results);
Now here comes the first log statement. The JavaScript execution does not halt to wait for the fetch to finish. That's the whole idea of asynchronous programming.Now, some time passes and finally, the data has finished loading.
return response.json();
The Promise returned from the fetch
gets fulfilled because the operation was successful. It then runs the callback that you provided earlier.moreInfo.value = responseObject;
if(j < movies.value.results.length)
{
movies.value.results[j].runtime = moreInfo.value.runtime;
console.log("print 1 "+movies.value.results[j]);
j++;
}
This is the second callback we created and same thing applies here. Now that the data is finally ready, this can be executed. I'm not sure about the whole j
thing, but apparently the execution will eventually get to the console.log("print 1 "+movies.value.results[j]);
statement.The important thing to understand here is that whether or not the 'print 1' statement was in the source code above the 'print 2' line is irrelevant. The 'print 1' was scheduled for later, namely, when the second fetch is done.
Fixed version
var info = //URL
fetch(info)
.then(function(response) { return response.json(); })
.then(function(responseObject) {
moreInfo.value = responseObject;
...
console.log("print 1 "+movies.value.results[j]);
...
})
.then(function(){
console.log("print 2 "+movies.value.results);
});
Now it could also be that I totally misunderstood the question. But if this was about asynchronicity, you should also check out the MDN Promise docs linked above and this SO question about asynchronicity in Node.js, which also applies to other JavaScript environments.
Upvotes: 3