倒数第二次未返回 promise 时调用递归 promise 时出现问题

Trouble calling recursive promise when promise isn't returned the second-to-last time

我正在尝试从 API 中递归获取数据,其中 returns 页数据。

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

这是到目前为止我得到的与此相关的代码:

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 的最后一次迭代中,函数 returns 是一个数组,而不是一个 promise。

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

该功能正在将页面停止到应在的位置。

错误是: Unhandled rejection TypeError: Cannot read property 'then' of undefined

非常感谢任何指导,尤其是关于设计模式的指导。

我知道哪里出了问题,但我该如何解决?

就目前而言,您有效拥有的是:

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() returns 未定义,因为 rp(...).then(...);
  2. 前面没有 return
  3. 内部 .then returns 未定义,因此递归的每一层(尝试)将 undefined 传递到上一层。
  4. 响应的转换需要在外部执行一次。然后内部应该从递归的下一个较低级别接收转换后的数据,而不是需要转换的原始响应。

您实际上已经完成了 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()returns承诺,无论是内部调用还是外部调用。
  • 递归的每个级别都提供来自所有较低级别的数据串联。
  • 递归的顶层向原始调用者提供来自所有较低层(即所有页面)的所有数据的完整串联。