如何打破 then 块中的 for 循环?

问题描述 投票:0回答:2

我是 Cypress 和 JavaScript 的新手。我想创建一个循环来执行具有不同值的请求,直到获得特定响应。

let continue_loop = 1;

loginLoop: for (let i = 1; i < 100; i++) {
  cy.request({
    // url: Cypress.env("web_api")+"/1.0/user/login",
    url: Cypress.env("api").staging + "/1.0/user/login",
    method: "POST",
    failOnStatusCode: false,
    body: {
      email: "email" + i + "@email.com",
      password: "Helloworld10",
    },
  }).then((response) => {
    if (response.status == 403) {
      continue_loop = 2;
    }
  });

  if (continue_loop == 2) {
    break loginLoop;
  }
}

看起来

continue_loop
只能在then块中获取值
2
,因为之后它总是返回1,所以循环永远不会中断。我也尝试使用 Cypress 别名,但结果相同。我怎样才能实现这个目标?

javascript promise cypress
2个回答
0
投票

令人烦恼的是,Cypress 不使用 Promise,而是使用“具有 .then 函数的东西”。当然,我们可以通过包装它们然后等待 那些 将这些变成

真正的承诺
const MAX_FAIL_COUNT = ...;

for (let failures = 0, i = 1; failures < MAX_FAIL_COUNT && i < 100; i++) {
  // Await the request with a simple wrapper
  const response = await new Promise(resolve => cy.request(
    ...
  ).then(resolve));

  // And don't use == unless your statement *only* works with type coercion
  if (response.status === 403) {
    failures++;
  }
}

0
投票

Cypress aliases 用于弥合同步代码(如 for 循环)和异步命令(如

cy.request()
)之间的差距。

你需要

  • 将代码检查
    break
    条件引入循环中,
  • 反转逻辑,只有当
    continue_loop
    true
  • 时才继续

这个可重现的示例展示了如何在 Cypress 测试中执行与

async/await
等效的逻辑。

let continue_loop = true

// set up the alias to control the loop
cy.wrap(continue_loop, {log:false}).as('continue')   

// staring at 95 to keep the example short
// #101 will be a failing request
// loops 102 to 200 will be skipped

for (let i = 95; i < 200; i++) {
  cy.get('@continue', {log:false}).then(continue_loop => {
    if (continue_loop) {
      cy.request({
        url: `https://jsonplaceholder.typicode.com/posts/${i}`,
        failOnStatusCode: false,
      }).then((response) => {

        // checking for any failed status here
        if (response.status >= 400) {
          continue_loop = false
          cy.wrap(continue_loop, {log:false}).as('continue')  // update the alias
        }
      })
    }
  })
}


带有 Promise 包装器

使用 Promise 包装器适用于这个简单的命令,但对于更复杂的命令链可能会失败。

Cypress 在控制台中发出警告。

for (let i = 95; i < 200; i++) {
  const response = await new Promise(resolve => {
    cy.request({
      url: `https://jsonplaceholder.typicode.com/posts/${i}`,
      failOnStatusCode: false,
    }).then(resolve)
  })
  if (response.status >= 400) {
    break 
  }
}

控制台中抛出的警告


请求投票

docs 中的这个示例是最简单的 IMO。

此模式使用递归而不是 for 循环。

function req(i) {
  if (i > 200) return    // highest number to try

  cy.request({
    url: `https://jsonplaceholder.typicode.com/posts/${i}`,
    failOnStatusCode: false,
  })
  .then((response) => {
    if (response.status >= 400) {
      return
    }
    req(++i)
  })
}

req(95)  // pass in the starting number (I use 95 to keep the example short)
© www.soinside.com 2019 - 2024. All rights reserved.