如何 return "then" 链中最后一个承诺的函数中的承诺

How to return a promise in a function from the last promise in a chain of "then"

我正在使用 Selenium 和 JavaScript 编写测试。我对两者都是新手,对函数式编程和 promises 也是新手。我正在尝试创建一个需要做 3 件事的函数:

  1. 点击输入
  2. 清除输入
  3. 发送输入键

我当前的功能不起作用:

    var clearAndSendKeys = function(driver, elementIdentifier, sendKeys) {
        var returnValue;
        driver.findElement(elementIdentifier).then(function(inputField){
            inputField.click().then(function() {
                inputField.clear().then(function() {
                    returnValue = inputField.sendKeys(sendKeys);
                });                 
            });                 
        });
        return returnValue;
    }

函数将被调用,例如:

    clearAndSendKeys(driver, webdriver.By.id('date_field'), '14.09.2015').then(function(){
        //Do stuff
    });

我希望变量 returnValue 包含来自 sendKeys 的承诺。但是函数 clearAndSendKeys returns sendKeys 之前的未定义变量是 运行。我认为这是因为 returnValue 从未被定义为承诺,因此程序不知道它需要等待 sendKeys.

如何使我的函数 clearAndSendKeys return 成为 sendKeys 的承诺?我宁愿避免必须向 clearAndSendKeys 函数添加回调。

编辑:从代码中删除了 .then({return data}),因为这是一个打字错误。

您必须 return 来自 .then 回调的每个承诺:

var clearAndSendKeys = function(driver, elementIdentifier, sendKeys) {
    return driver.findElement(elementIdentifier).then(function(inputField){
        return inputField.click().then(function() {
            return inputField.clear().then(function() {
                return inputField.sendKeys(sendKeys);
            });                 
        });                 
    });
}

.then 编辑的承诺 return 将解析为与 return 从回调中编辑的值相同的值。


请参阅 Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference 以了解为什么您当前的代码不起作用。 Promise 是 异步的 .

首先,嵌套 promise 可能不是最好的主意,完全违背了消除回调地狱的主要目的。 then 回调可以 return Thenable 允许创建漂亮的异步操作链的对象。

在这种情况下,您只需要存储对作为主函数范围内第一个异步操作的结果可用的输入字段的引用,然后创建可以从 return 编辑的异步操作链这个函数。

var clearAndSendKeys = function(driver, elementIdentifier, sendKeys) {
    var inputFieldRef;
    return driver.findElement(elementIdentifier)
        .then(function(inputField){
            inputFieldRef = inputField;
            return inputField.click();
        }).then(function() {
            return inputFieldRef.clear();
        }).then(function() {
            return inputFieldRef.sendKeys(sendKeys);
        });
}