【问题标题】:How to break out of a loop from a returned promise value?如何从返回的承诺值中跳出循环?
【发布时间】:2016-01-15 20:58:43
【问题描述】:

对 javascript 有点陌生,但根据我的阅读,promise 中的所有值基本上只能在该 promise 中使用,对吧?

基本上 getSomething() 从另一个承诺返回真/假。如果为真,我将跳出 for 循环。我试过这样的东西,但我确定它不正确,因为它没有打印出“打破”

for(...) {
    var bool = this.getSomething(a,b,c).then((flag) => {
        if (flag == true) {
            console.log('returning true');
            return true; // can't use break so have to set boolean - eslint gives me unsyntactical break
        }
    });

    if (bool == true) {
        console.log('breaking');
        break;
    }
}

getSomething(a,b,c) {
    const n = b[a].element(by.binding('something'));
    return n.getText().then((text) => {
        if (text === c) {
        return clickSomething();        // returns true after click()
        }
    });
}

我之所以使用for循环是因为我需要在strong标签中找到匹配的文本,然后点击它下面td标签中的按钮。

<tbody>
    <tr ng-repeat="something">
        <td>
            <strong>{{x.name}}</strong>
        </td>
        <td>
            <button>{{x.button}}</button>
        </td>
    </tr>
</tbody>

【问题讨论】:

  • 你不能在 for 循环中使用 Promise。 Promise 是异步的,这意味着它们只会在所有其他同步代码运行之后才会运行。
  • @MikeC 为什么之后?它们将同时运行。
  • @Calin 我的意思是.then 函数在所有同步代码完成之前不会执行。与使用 setTimeoutsetInterval 的想法相同。
  • @MikeC 然后会返回一个新的promise,回调函数(它有一个语法错误)一旦有人在这个promise上调用resolve就会被执行,没有人在这段代码中这样做。我认为发帖人需要对承诺做更多的阅读。
  • @Calin then 回调很好。这是一个arrow function。是的,它会返回一个承诺,这明确意味着该值将无法及时访问到 break 循环之外。请参阅 alecxe 的回答。

标签: javascript angularjs protractor


【解决方案1】:

其中涉及 Protractor 添加到 Control Flow queue 的 Promise,您无法像通常在同步“从上到下”代码中那样读取和处理 for 循环 + break。

此问题的常见解决方案是使用递归+闭包,请参阅此处的示例解决方案:


我之所以使用for循环是因为我需要在strong标签中找到匹配的文本,然后点击它下方td标签中的按钮。

一种选择是使用by.xpath() locator

element(by.xpath("//td[strong = '" + label + "']/following-sibling::td/button")).click();

其中label 是您要查找的strong 值。

或者,更具体的量角器方法是使用filter()

var rows = element.all(by.repeater("something"));

var filteredRow = rows.filter(function (row) {
    return row.element(by.binding("x.name")).getText().then(function (name) {
        return name === label; 
    });
}).first();

filteredRow.element(by.binding("x.button")).click();

【讨论】:

  • 你能看看我的更新吗?我查看了您的答案stackoverflow.com/a/31208548/4188135 和其他人,但它们似乎适用于在匹配的行/标签上执行 click() 操作的实例。但我需要以某种方式对转发器返回的第二行执行操作。希望这是有道理的
  • @yob-v-u 当然,感谢您使问题更加具体。更新了答案,希望对您有所帮助。
【解决方案2】:

如果你真的想做这样的事情,你必须使用when,它会返回一个新的承诺。

when(promise1, promise2, promise3).done( function (promise1, promise2, promise3) {
}
  • 当所有给定的 Promise 都被解决后,新的 Promise 也被解决了
  • 当一个承诺失败时,新的承诺也会失败

【讨论】:

  • 谢谢,你能分享更多when使用的例子吗?也许是一个链接
猜你喜欢
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
  • 2020-11-24
  • 2019-03-01
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
相关资源
最近更新 更多