How to return a promise in a function from the las

2019-06-14 02:38发布

问题:

I'm writing a test using Selenium and JavaScript. I'm new to both, and also new to functional programming and promises. I'm trying to create a function that needs to do 3 things:

  1. Click on an input
  2. Clear the input
  3. SendKeys to input

My current function does not work:

    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;
    }

The function would then be called as for example:

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

I expected the variable returnValue to contain the promise from sendKeys. However the function clearAndSendKeys returns the undefined variable before sendKeys is ran. I assume this is because returnValue was never defined as a promise, and so the program does not know that it needs to wait for sendKeys.

How can I make my function clearAndSendKeys return the promise from sendKeys? I'd rather avoid having to add a callback to the clearAndSendKeys function.

Edit: Removed .then({return data}) from the code as this was a typo.

回答1:

You have to return each promise from the .then callback:

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);
            });                 
        });                 
    });
}

The promise returned by .then will resolve to the same value as the value returned from the callback.


See Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference for why your current code does not work. Promises are asynchronous.



回答2:

First of all its probably not the best idea to nest promises, completely defeating their main purpose of eliminating callback hell. then callback can return Thenable object that allows to create nice chains of async operations.

In this case you just need to store reference to input field available as a result of the first async operation in the scope of the main function and then create chain of async operations that can be returned from this function.

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);
        });
}