Good day all,
I'm working on extracting some data out of PipeDrive's API using Axios for Node.js. The way that PipeDrive developed their API pagination is a bit different. Here is how their pagination indicator looks:
"additional_data": {
"pagination": {
"start": 0,
"limit": 100,
"more_items_in_collection": true,
"next_start": 100
}
}
I need to interate through all pages to extract the data, and my code has successfully done that, but I cannot get my promise to resolve for some reason.
My logic in the code is as follows:
if(more_items_in_collection){Add current page's data then re-run the same function with the next_start as a parameter}
else{Add current page's data then RESOLVE the promise to complete the function}
But this resolution never happens, even though my code works (strange).
Gurus, can you please take a look at my code and let me know why you think it won't resolve (function().then((result) => {OUTPUT})
never returns happens)?
Thanks as always!
const queryPipeDrive = (start) =>{
// Query is a full then-able Async function
return new Promise((resolve, reject) => {
// API CALL
axios({
method: 'GET',
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start
}
})
// THEN DO THIS
.then((response) => {
// IF there are more items in collection on additional pages, iterate through the pages
if(response.data.additional_data.pagination.more_items_in_collection){
// Add all deals on page to the container
for (const deal of response.data.data) {
db.get('deals').push(deal) // Push deal data to the StormDB File
}
console.log(chalk.cyan(`${response.data.additional_data.pagination.next_start}`))
// Function loop created. We will loop UNTIL the 'more_items_in_collection' prop is false, then we'll resolve the promise.
queryPipeDrive(response.data.additional_data.pagination.next_start)
}else{
// Add all deals on this page to the reponse container
for (const deal of response.data.data) {
db.get('deals').push(deal)
}
db.save() // Save changes to temp DB
resolve(response.data.data) // Resolve Promise with the data from the successful call
}
})
.catch((err) => {
console.log(chalk.red(err))
reject(err)
})
})
}
Your more_items_in_collection case never resolves the promise. It just creates a new one, then does nothing with it.
Additionally, you're making your code more complicated than it needs to be by using new Promise
. Axios already returns a promise, so there's no need to explicitly create a new one. Calling .then
will create a new promise automatically, which resolves to whatever value you return in the callback.
const queryPipeDrive = (start) => {
// API CALL
return axios({
method: "GET",
url: pipeDriveURI,
params: {
api_token: apiKey,
start: start,
},
})
// THEN DO THIS
.then((response) => {
// IF there are more items in collection on additional pages, iterate through the pages
if (response.data.additional_data.pagination.more_items_in_collection) {
// Add all deals on page to the container
for (const deal of response.data.data) {
db.get("deals").push(deal); // Push deal data to the StormDB File
}
console.log(
chalk.cyan(`${response.data.additional_data.pagination.next_start}`)
);
// Function loop created. We will loop UNTIL the 'more_items_in_collection' prop is false, then we'll resolve the promise.
return queryPipeDrive(
response.data.additional_data.pagination.next_start
);
} else {
// Add all deals on this page to the reponse container
for (const deal of response.data.data) {
db.get("deals").push(deal);
}
db.save(); // Save changes to temp DB
return response.data.data;
}
})
.catch((err) => {
console.log(chalk.red(err));
throw err;
});
};