Node.js - 承诺不在循环内解决

Node.js - Promise not resolving within loop

大家好,

我正在使用 Axios for Node.js 从 PipeDrive 的 API 中提取一些数据。 PipeDrive 开发其 API 分页的方式有点不同。这是他们的分页指示器的外观:

    "additional_data": {
    "pagination": {
        "start": 0,
        "limit": 100,
        "more_items_in_collection": true,
        "next_start": 100
    }
}

我需要遍历所有页面以提取数据,我的代码已成功完成,但由于某种原因我无法得到解决的承诺。

我的代码逻辑如下:

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}

但是这个解决方案永远不会发生,即使我的代码有效(奇怪)。

大师,能否请您看看我的代码并告诉我为什么您认为它无法解析(function().then((result) => {OUTPUT}) 从未 returns 发生)?

一如既往的感谢!

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

}

您的 more_items_in_collection 案例永远无法兑现承诺。它只是创建一个新的,然后什么也不做。

此外,使用 new Promise 会使代码变得比需要的更复杂。 Axios 已经 return 是一个承诺,所以没有必要明确地创建一个新的。调用 .then 将自动创建一个新的承诺,它解析为您在回调中 return 的任何值。

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

除了已接受的答案。

你会考虑在 await 中使用这个异步函数吗?这样,你就调用了main().

const main = async start => {
  const res = await queryPipeDrive(start);
  if (res.isMoreItems === true) {
    await main(res.nextStart);
  }
};

async function queryPipeDrive(start) {
  const response = await axios({
    method: "GET",
    url: pipeDriveURI,
    params: {
      api_token: apiKey,
      start: start,
    },
  });

  for (const deal of response.data.data) {
    db.get("deals").push(deal);
  }

  if (response.data.additional_data.pagination.more_items_in_collection) {
    console.log(
      chalk.cyan(`${response.data.additional_data.pagination.next_start}`)
    );
    return {
      isMoreItems: true,
      nextStart: response.data.additional_data.pagination.next_start,
    };
  } else {
    db.save(); // Save changes to temp DB
    return {
      isMoreItems: false,
    };
  }
}