【问题标题】:Passing WebElement object in deferred.resolve在 deferred.resolve 中传递 WebElement 对象
【发布时间】:2014-04-27 17:13:06
【问题描述】:

下面的代码找到一个带有量角器(一个身份验证按钮)的 webElement,并尝试以该元素作为参数来解析一个 Promise。

function someFunc() {
    var deferred = q.defer();
    browser.findElement(by.css('[data-aid="buttons.authenticate"]')).then(
        function(e) {
            console.log('element found: ' + e);
            deferred.resolve(e);
        }
    );
    return deferred.promise;
}

someFunc().then(
        function(elem) {
            console.log('got elem ' + elem);
            elem.click();
        }
    );

输出: element found: [object Object]
所以 then 函数永远不会被调用。当我用其他值(int,string,array,map)替换resolve()时,它工作正常。那为什么我不能返回一个 WebElement 对象呢?

谢谢你

【问题讨论】:

  • 找到一个元素然后点击它是你的最终用例吗?我问是因为如果是这样,那么我认为有更简单的方法和更少的代码。
  • 其实...browser.findElement(by.css('[data-aid="buttons.authenticate"]')).click() 会这样做,我怀疑。
  • 这只是一个更复杂案例的简单示例 - 最终我想用另一个“包装”返回的承诺。在这个例子中,我想从外面做click()。为此,我需要WebElement 对象

标签: javascript webdriver promise protractor


【解决方案1】:

要实际执行您的要求,我怀疑您应该使用 Webdriver Promise API 而不是 q,公开为 protractor.promise

var deferred = protractor.promise.defer();

使用fulfill function 而不是resolve

deferred.fulfill(e);

不过……

如果您通过defer 创建一个promise 只是为了对一个或多个现有promise 做某事,这通常表明您没有使用promise 链接或可用的API 函数,如果可以的话。链接可以通过返回 a) 你想从 then 回调中解析的内容和 b) 返回 then 函数的结果来完成:

function someFunc() {
  return browser.findElement(by.css('[data-aid="buttons.authenticate"]')).then(function(e) {
    console.log('element found: ' + e);
    return e;
  });
}

someFunc().then(function(elem) {
  console.log('got elem ' + elem);
  elem.click();
});

但是因为在本例中,您返回的正是承诺的已实现值,所以可以进一步简化:

function someFunc() {
  return browser.findElement(by.css('[data-aid="buttons.authenticate"]'));
}

someFunc().then(function(elem) {
  console.log('got elem ' + elem);
  elem.click();
});

而且,因为click实际上暴露在findElement的promise结果上,这可以进一步简化为

browser.findElement(by.css('[data-aid="buttons.authenticate"]').click();

您在 cmets 中说您不能执行上述操作,因为您想“包装”承诺。不太清楚这意味着什么,但假设你想要有 2 个元素可用以便对它们做一些事情,你可以使用 protractor.promise.all,而不是通过 defer 手动创建承诺:

var button1 = browser.findElement(by.css('[data-aid="buttons.authenticate"]');
var button2 = browser.findElement(by.css('[data-aid="buttons.confirm"]');

protractor.promise.all([button1, button2]).then(function(buttons) {
  var button1 = buttons[0];
  var button2 = buttons[1];
  // Do something with both buttons   
});

还有其他功能可以以各种方式操纵 Promise Webdriver's Promise API。 'map' 和 'filter' 我认为是我用过的。

【讨论】:

  • fulfill 成功了。你能解释一下你是怎么理解q不合适的吗?谢谢。
  • 我知道 Protractor 使用 Webdriver Promise,它与 control flow 相关联。任何其他承诺实现,比如来自 Node 的 require('q')q,我怀疑不会对控制流做任何事情,并且会导致奇怪的事情,因为事情可以在意想不到的时间用意想不到的值解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
相关资源
最近更新 更多