我试图通过在循环中使用
cy.intercept()
来拦截每 10 秒自动刷新一次的 API 调用。当状态设置为“完成”时,循环应该中断。不幸的是 cy.intercept()
只被调用一次,我尝试调试它,我可以在控制台中看到该函数只被调用一次,然后即使状态未设置为“已完成”也会中断。我做错了什么?
export function stubBackendResponse(id: string): void {
let iterations = 0;
const maxIterations = 10;
const intervalMs = 30000;
function checkStatusAndLoop(): void {
cy.intercept({
method: "GET",
url: `/api/${id}`,
}).as("data");
cy.wait("@data")
.its("response.body")
.should((data) => {
const status = data[0].status;
if (status !== "completed" && iterations < maxIterations) {
iterations++;
setTimeout(checkStatusAndLoop, intervalMs);
} else if (
status !== "completed" &&
iterations >= maxIterations
) {
throw new Error("Max iterations reached. Status is not 'completed'.");
}
});
}
checkStatusAndLoop();
}
问题可能是试图在
.should()
断言的回调中递归。
通常回调只会触发断言(expect、assert)而不会改变代码流程。
您可以尝试这种方式,在普通函数中调用递归。 如果您发出新的
setTimeout()
作为递归步骤,则不需要 cy.wait("@data")
。
let iterations = 0;
const maxIterations = 10;
function checkStatus(interception => {
if (iterations >= maxIterations) {
throw new Error("Max iterations reached. Status is not 'completed'.")
}
const status = response.body[0].status
if (status !== "completed" && iterations < maxIterations) {
iterations++;
cy.wait("@data").then(checkStatus)
}
})
cy.intercept({method: "GET", url: `/api/${id}`})
// visit the page to trigger the polling
cy.wait("@data").then(checkStatus)
另一个选项是动态别名虽然我不知道是否可以在响应阶段分配别名(示例是在请求阶段)。
let iterations = 0;
const maxIterations = 10;
cy.intercept({method: "GET", url: `/api/${id}`}, (req) => {
iterations++
if (iterations >= maxIterations) {
throw new Error("Max iterations reached. Status is not 'completed'.")
}
req.continue(response => {
const status = response.body[0].status;
if (status === "completed") {
req.alias = 'data'
}
})
})
cy.wait("@data") // won't be set until response is correct,
// but this may be a chicken and egg failure