Search code examples
javascriptnode.jspromisees6-promise

Node.js - Promise not resolving within loop


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)
     })
 })

}


Solution

  • 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;
        });
    };