倒数第二次未返回 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();
我遇到的问题是:
在 hasNextPage
为 false
的最后一次迭代中,函数 returns 是一个数组,而不是一个 promise。
这很好,但是在倒数第二个迭代中,我们检测到 hasNextPage
是 true
,然后再次调用该函数。但是,我们不能对该结果执行 .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;
}
});
}
几个问题:
getPhaseData()
returns 未定义,因为 rp(...).then(...);
前面没有 return
- 内部 .then returns 未定义,因此递归的每一层(尝试)将
undefined
传递到上一层。
- 响应的转换需要在外部执行一次。然后内部应该从递归的下一个较低级别接收转换后的数据,而不是需要转换的原始响应。
您实际上已经完成了 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承诺,无论是内部调用还是外部调用。
- 递归的每个级别都提供来自所有较低级别的数据串联。
- 递归的顶层向原始调用者提供来自所有较低层(即所有页面)的所有数据的完整串联。
我正在尝试从 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();
我遇到的问题是:
在 hasNextPage
为 false
的最后一次迭代中,函数 returns 是一个数组,而不是一个 promise。
这很好,但是在倒数第二个迭代中,我们检测到 hasNextPage
是 true
,然后再次调用该函数。但是,我们不能对该结果执行 .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;
}
});
}
几个问题:
getPhaseData()
returns 未定义,因为rp(...).then(...);
前面没有 - 内部 .then returns 未定义,因此递归的每一层(尝试)将
undefined
传递到上一层。 - 响应的转换需要在外部执行一次。然后内部应该从递归的下一个较低级别接收转换后的数据,而不是需要转换的原始响应。
return
您实际上已经完成了 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承诺,无论是内部调用还是外部调用。- 递归的每个级别都提供来自所有较低级别的数据串联。
- 递归的顶层向原始调用者提供来自所有较低层(即所有页面)的所有数据的完整串联。