javascript - 当 Promise 倒数第二次未返回时,调用递归 Promise 时出现问题

标签 javascript recursion promise request-promise

我正在尝试从 API 中递归获取数据,该 API 返回页面中的数据。

我想继续获取数据并将结果附加到数组中,直到 hasNextPage 为 false。

这是迄今为止我与此相关的代码:

function getPhaseData(cursor) {
  let cursorAddition = "";
  if (cursor === undefined) {
    cursorAddition = "";
  } else {
    cursorAddition = ' after: "' + cursor + '"';
  }
  // build the API request - have no cursor/starting position on the initial calls, but add it on the subsequent calls

  let phaseData = [];
  // eventually want to return this variable with all the data from the API

  rp({
    url: "https://app.pipefy.com/queries",
    method: "POST",
    headers: {
      Authorization: "Bearer " + process.env.PIPEFY_BEARER,
      "Content-Type": "application/json"
    },
    mode: "no-cors",
    body:
      '{"query":"{ phase(id: 2087517) {id name cards_count cards (first: 30' +
      cursorAddition +
      ') {  pageInfo { endCursor hasNextPage } edges { node { id title due_date } } } }}"}'
  }).then(function(response) {
    let responseData = JSON.parse(response);

    for (var i in responseData.data.phase.cards.edges) {
      phaseData.push(responseData.data.phase.cards.edges[i]); // add the data from the first call to the phaseData array
    }

    if (responseData.data.phase.cards.pageInfo.hasNextPage) { // if next page exists
      // call function again to get the next page, starting from the cursor position
      return getPhaseData(responseData.data.phase.cards.pageInfo.endCursor).then(function(nextResponse) {
        let nextResponseData = JSON.parse(nextResponse);
        for (var i in nextResponseData.data.phase.cards.edges) {
        phaseData.push(nextResponseData.data.phase.cards.edges[i]); // add the data from the subsequent calls to the phaseData variable
      }
      });
    } else {
      return phaseData; // if no subsequent page exists, just return the phase data
    }
  });
}

getPhaseData();

我遇到的问题是:

在最后一次迭代中,当 hasNextPagefalse 时,该函数返回一个数组,而不是一个 Promise。

这很棒,但在倒数第二次迭代中,我们检测到 hasNextPagetrue,并再次调用该函数。但是,我们无法对该结果执行 .then(),因为返回的是数组而不是 promise !

该函数在距离应有位置不足的一页处停止。

错误是: 未处理的拒绝类型错误:无法读取未定义的属性“then”

我很感激任何指导,特别是关于设计模式的指导。

我可以看出哪里出了问题,但是我该如何解决它?

最佳答案

就目前情况而言,您实际上拥有的是:

function getPhaseData(cursor) {
    // synchronous stuff
    rp({ ... })
    .then(function(response) {
        let phaseData = someTransformOf(response);
        if (testForNextPage) {
            return getPhaseData(response.someProperty)
            .then(function(nextResponse) {
                phaseData = phaseData.concat(someTransformOf(nextResponse));
            });
        } else {
            return phaseData;
        }
    });
}

几个问题:

  1. getPhaseData()返回未定义,因为没有 return前面rp(...).then(...);
  2. 内部 .then 返回未定义,因此每个递归级别(尝试)传递 undefined达到之前的水平。
  3. 响应的转换需要在外部 then 中执行一次。内部 then 应该从递归的下一个较低级别接收转换后的数据,而不是需要转换的原始响应。

你实际上已经完成了 90% - 修复方法非常简单:

function getPhaseData(cursor) {
    // synchronous stuff
    return rp({ ... })
 // ^^^^^^ 
    .then(function(response) {
        let phaseData = someTransformOf(response);
        if (testForNextPage) {
            return getPhaseData(response.someProperty)
            .then(function(nextResponse) {
                return phaseData.concat(nextResponse); // no need to perform the transform here, it was performed by the recursive getPhaseData() call
             // ^^^^^^
            });
        } else {
            return phaseData;
        }
    });
}

现在,

  • getPhaseData()返回 Promise,无论是内部调用还是外部调用。
  • 每个递归级别都会提供来自所有较低级别的数据的串联。
  • 递归的顶层向原始调用者提供来自所有较低级别(即所有页面)的所有数据的完整串联。

关于javascript - 当 Promise 倒数第二次未返回时,调用递归 Promise 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60103479/

相关文章:

javascript - AngularJS 中的 DataTable 导出按钮

javascript - 将获取的州和城市名称永久存储到文件中

javascript - axios 在 componentDidMount 中获取数据后如何拍摄快照?

javascript - 使用 Promise 链接 http 请求

javascript - window.URLSearchParams 在 Edge 上损坏

javascript - field 的谷歌地图地理编码器

linux - 如何按上次更新日期列出父目录,包括该文件夹的所有文件

C++ - 置换函数

python - 调用 super 的 init 时 Python 中的最大递归深度错误。

javascript - 如果我执行一个进行异步调用的函数,如果执行循环,如何让函数的其余部分在执行之前等待调用?