I'm in a scenario where I have to get data from the server in parts in sequence, and I would like to do that with the help of Promises. This is what I've tried so far:
function getDataFromServer() {
return new Promise(function(resolve, reject) {
var result = [];
(function fetchData(nextPageToken) {
server.getData(nextPageToken).then(function(response) {
result.push(response.data);
if (response.nextPageToken) {
fetchData(response.nextPageToken);
} else {
resolve(result);
}
});
})(null);
});
}
getDataFromServer().then(function(result) {
console.log(result);
});
The first fetch is successful, but subsequent calls to server.getData()
does not run. I presume that it has to do with that the first then()
is not fulfilled. How should I mitigate this problem?
The Promise.allmethod returns a promise when all the promises inside the promisesarray is resolved. So, this is how you can use promise inside a for each loop. A similar approach can be applied to use promise inside for loop or while in JavaScript or Node.js.
The function itself returns a promise that allows you to wait until the loop has finished and the handler function that you pass may also return a promise. It took me some time to get it right, but I believe the following code will be usable in a lot of promise-looping situations.
This second promise ( promise2) represents the completion not just of doSomething (), but also of the successCallback or failureCallback you passed in, which can be other asynchronous functions returning a promise.
Luckily we can wrap setTimeout in a promise. Best practice is to wrap problematic functions at the lowest possible level, and then never call them directly again: const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback);
Nimrand answers your question (missing catch
), but here is your code without the promise constructor antipattern:
function getDataFromServer() {
var result = [];
function fetchData(nextPageToken) {
return server.getData(nextPageToken).then(function(response) {
result.push(response.data);
if (response.nextPageToken) {
return fetchData(response.nextPageToken);
} else {
return result;
}
});
}
return fetchData(null);
}
getDataFromServer().then(function(result) {
console.log(result);
})
.catch(function(e) {
console.error(e);
});
As you can see, recursion works great with promises.
var console = { log: function(msg) { div.innerHTML += "<p>"+ msg +"</p>"; }};
var responses = [
{ data: 1001, nextPageToken: 1 },
{ data: 1002, nextPageToken: 2 },
{ data: 1003, nextPageToken: 3 },
{ data: 1004, nextPageToken: 4 },
{ data: 1005, nextPageToken: 0 },
];
var server = {
getData: function(token) {
return new Promise(function(resolve) { resolve(responses[token]); });
}
};
function getDataFromServer() {
var result = [];
function fetchData(nextPageToken) {
return server.getData(nextPageToken).then(function(response) {
result.push(response.data);
if (response.nextPageToken) {
return fetchData(response.nextPageToken);
} else {
return result;
}
});
}
return fetchData(0);
}
getDataFromServer().then(function(result) {
console.log(result);
})
.catch(function(e) { console.log(e); });
<div id="div"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With