Protractor循环中getText()后索引值异常问题排查及修正请求
问题分析与修复:Protractor循环中索引值异常的闭包陷阱
Hey there! Let's figure out why your index values are misbehaving and fix that issue.
问题根源:异步回调与闭包的冲突
你碰到的是JavaScript里非常经典的闭包陷阱。核心原因是:getText().then()里的回调函数是异步执行的——当这些回调真正触发的时候,外层的for...in循环已经完全跑完了,变量i已经变成了数组的最后一个索引值(也就是你看到的10)。所有回调函数共享同一个i变量,所以它们最后输出的都是循环结束后的最终值,自然没法拿到正确的行索引。
解决方案:让每个迭代的索引值独立
这里有两种可靠的修复方式,推荐第一种更简洁的写法:
方案1:使用forEach遍历数组(推荐)
forEach的每个迭代都会创建一个独立的作用域,每个回调里的index参数都是当前迭代的固定值,不会被后续循环修改。修改后的代码如下:
element(by.repeater('cat in cats').column('cat.name')).then(function(fields) { fields.forEach(function(field, index) { console.log(index); // 输出0到9(对应数组长度10) field.getText().then(function(fieldValue) { console.log(index); // 这里的index和外层完全对应,不会跑偏 if(fieldValue === 'Meow') { var catAge = element(by.repeater('cat in cats').row(index)).element(by.model('cat.age')); expect(catAge.getAttribute('value')).toBe('10'); } }); }); });
方案2:用立即执行函数(IIFE)封闭索引值
如果坚持要用for...in循环,可以用立即执行函数表达式(IIFE)把每次循环的i值封装起来,为每个回调创建独立的作用域:
element(by.repeater('cat in cats').column('cat.name')).then(function(fields) { for (var i in fields) { console.log(i); // 输出0到10 // 用IIFE捕获当前的i值,避免后续循环修改它 (function(currentIndex) { fields[currentIndex].getText().then(function(fieldValue) { console.log(currentIndex); // 输出对应迭代的索引值 if(fieldValue === 'Meow') { var catAge = element(by.repeater('cat in cats').row(currentIndex)).element(by.model('cat.age')); expect(catAge.getAttribute('value')).toBe('10'); } }); })(i); } });
小提示
为什么更推荐forEach?它不仅写法更简洁易读,还能避免for...in遍历数组时可能出现的意外问题(比如遍历到数组原型链上的额外属性),更符合现代JavaScript的编码习惯。
内容的提问来源于stack exchange,提问作者9094US
相关产品推荐
相关产品推荐

