Cypress测试中JS异步执行顺序问题及解决方案咨询
问题:Cypress中提取数字后执行顺序异常的问题
我认为这是一个常见的JavaScript问题而非Cypress测试问题,但不确定。我有一个Web UI,会显示类似found 3234 matches的文本消息,希望用Cypress提取数字3234,然后在后续页面的输入框中填入该数字。
我的代码如下:
const MATCHING_MESSAGE = '[data-cy=matchingMessages]'; let count = 0; cy.get(MATCHING_MESSAGE) .invoke('text') .then((text) => { const pattern = /[0-9]+/g; count = text.match(pattern).pop(); console.log({count1: count}); }) // 跳转到下一页 console.log({count2: count}); if (count > 0) { // 输入count值 } else { // 输入最小值如5 }
执行后浏览器控制台输出:
log: count2: 0 log: count1: 3234
导致后续页面始终判定count为0,现存在三个疑问:
- 已知是执行顺序问题,但为何
count2: 0的日志在跳转到第二页前就输出? - 关于JS执行顺序和Promise,我缺少哪些相关知识?
- 是否有方法强制执行代码顺序?
问题解答
1. 为什么count2:0先输出?
Cypress的命令(比如cy.get、cy.invoke)都是异步队列执行的,它们不会阻塞主线程。你写的console.log({count2: count})和后面的if判断是同步代码,会在Cypress异步队列还没开始执行的时候就直接运行。而cy.get里的.then回调是异步的,要等Cypress完成DOM查询、获取文本这些操作后才会触发,所以count1的日志会晚于count2。
2. 需要补充的JS执行顺序和Promise知识
- 同步任务 vs 异步任务:JS是单线程,同步任务会在主线程里按顺序立即执行;异步任务(比如Promise回调、Cypress命令这类基于Promise的操作)会被放到任务队列,等主线程空了才会执行。
- Cypress的命令队列:Cypress的所有命令都不是立即执行,而是先加入一个队列,等当前同步代码全部跑完后,才会依次执行队列里的命令。
.then是附着在Cypress命令上的回调,只有当前面的命令执行完成后才会触发。 - 变量赋值的时机:你用全局的
count变量,同步代码读取它的时候,异步回调还没修改它,所以拿到的是初始值0。
3. 如何强制执行代码顺序?
要让后续操作(跳转页面、输入值)等待异步提取数字的操作完成,必须把这些逻辑放到.then回调内部,或者用Cypress的链式调用:
const MATCHING_MESSAGE = '[data-cy=matchingMessages]'; cy.get(MATCHING_MESSAGE) .invoke('text') .then((text) => { const pattern = /[0-9]+/g; const count = text.match(pattern).pop(); console.log({count1: count}); // 把跳转和输入逻辑放到这里,确保count已经被赋值 // 跳转到下一页(替换成你实际的跳转命令,比如cy.visit或点击按钮) cy.get('[data-cy=next-page-btn]').click(); if (count > 0) { cy.get('[data-cy=target-input]').type(count); } else { cy.get('[data-cy=target-input]').type('5'); } })
核心原则是:所有依赖异步结果的代码,都必须放在异步回调或者链式调用的后续步骤里,不能和同步代码平级写。这样就能保证代码严格按照你期望的顺序执行。
内容的提问来源于stack exchange,提问作者Robinson Wei
相关产品推荐
相关产品推荐

