我正在尝试从 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();
我遇到的问题是:
在最后一次迭代中,当 hasNextPage
为 false
时,该函数返回一个数组,而不是一个 Promise。
这很棒,但在倒数第二次迭代中,我们检测到 hasNextPage
为 true
,并再次调用该函数。但是,我们无法对该结果执行 .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;
}
});
}
几个问题:
-
getPhaseData()
返回未定义,因为没有return
前面rp(...).then(...);
- 内部 .then 返回未定义,因此每个递归级别(尝试)传递
undefined
达到之前的水平。 - 响应的转换需要在外部 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/