Monday, June 17Be an Automation Engineer

async / await to avoid control flow

Many of us might have heard of control flow while using selenium based automation tools like selenium-webdriver(Javascript), protractor etc..

A brief idea about control flow for those who does not know about control flow.

What is control flow?
“WebDriverJS (and thus, Protractor) APIs are entirely asynchronous. All functions return promises. WebDriverJS maintains a queue of pending promises, called the control flow, to keep execution organized.”

How control flow maintains creates a queue of promises while executing our code?

Assume that we have created a protractor script by following jasmine framework as below.

describe('Control flow explanation example spec', function() {
    it('should find an element by text input model', function () {

        element(by.model('yourName')).sendKeys('Jane Doe');

        var welcomeText = element(by.binding('yourName')).getText();

        expect(welcomeText).toEqual('Hello Jane Doe!');


All the Protractor code written above are asynchronous by nature. Protractor will arrange the above code as chain of promises to let it execute in a sequential way. So that our code will hit the browser in a synchronous manner as written line by line. 

The protractor converted code will look like below.

describe('Control flow explanation example spec', function () {
    it('should find an element by text input model', function () {
            .then(function () {
                return element(by.model('yourName')).sendKeys('Jane Doe');
            }).then(function () {
                return element(by.binding('yourName')).getText();
            }).then(function (welcomeText) {
                expect(welcomeText).toEqual('Hello Jane Doe!');

Here you can observe that all your code lines are moved to then block of previous line. This is how protractor executes asynchronous code in a synchronous way. This is called control flow. 

Note: Control flow is actually designed by selenium-webdriver. Protractor is using control flow to execute it’s code in a synchronous way. 

Why protractor is deprecating control flow?

Protractor is ultimately depends on selenium-webdriver’s control flow as I said in my note about. Selenium-webdriver is deprecating the control flow to avoid few known and unavoidable issues with it particularly while writing native javascript code along with protractor code. Also, Node.js is now supporting async /await since it’s 7.6 release. So promises world will be easy with async / await. 

How to use async /await in protractor?

Most of the folks suggested to disable disable control flow, if we want to use async / await. Control flow becomes unreliable if we use control flow along with async await. We should add the below line into the protractor config file to disable the control flow.


If your project is big and you would like to shift to async/await, it is difficult for you to disable control flow and let the specs fail until the async/await code refactoring is done. So, I kind of suggest you not to disable control flow and convert the code to async/await in parallel. I know, this is contradicting the above statement. But, from my experience it is ok to let control flow and async await run in parallel.

Make sure your node version is at least 7.6 or above

Let’s see an example

describe('Control flow explanation example spec', function () {
    it('should find an element by text input model', async function () {
        await browser.get('');
const yourNameTextField = element(by.model('yourName')); await element(by.model('yourName')).sendKeys('Jane Doe'); const welcomeText = await element(by.binding('yourName')).getText(); expect(welcomeText).toEqual('Hello Jane Doe!'); }); });

From the above snippet, we need to notice two main points.



 it('should find an element by text input model', function () {  


 it('should find an element by text input model', async function () {  


Also, I have not used await for const yourNameTextField = element(by.model('yourName'));.
Means, element(...) does not return promise.

More details:

If we are using awaitin any function, whether it could be standalone function or a call back function, we need to mark the function with async.
So, sample async function would look like:

async function sampleFunction(){
    await <some other async method call>;
await sampleFunction();

Also, we can mark a function which returns promise with async

async function valueShouldBeUnder10(val) {
    return new Promise(function(resolve,reject) {
        setTimeout(function () {
            console.log('timeout completed'); 
        }, 1000); 
        if(val<10) {
            resolve('Val is under 10');
            reject('val is not under 10');
await valueShouldBeUnder10(5);
%d bloggers like this: