1

I'd like to try to randomize the order of filling out form fields.

async function processForm() {

    ....

    async function timeout(ms) {
        return new Promise(resolve => setTimeout(resolve, ms*(Math.random() +.5)));
    }
    async function func1() {
      await page.type(...);
    }
    async function func2() {
      await page.type(...);
    }
    async function func3() {
      await page.click(...);
    }
    async function func4() {
      await page.click(...);
    }


        var a = function () { func1(); },
            b = function () { func2(); },
            c = function () { func3(); },
            d = function () { func4(); },
            array = [a, b, c, d];

        array = array.map(function (a, i, o) {
            var j = (Math.random() * (o.length - i) | 0) + i,
                t = o[j];
            o[j] = a;
            return t;
        });
        for ( const a of array) {
            await timeout(4000);
            await a();
        }
        await timeout(4000);
        await page.click("button[type='submit']");
....
}

I tried sticking console.log statements in each function and after the submit. I find that it indeed is random, but sometimes the submit occurs before the 4 func.
I used this example (JavaScript random order functions) to randomize but I am struggling to have them be called sequentially. I thought that with async functions and await, it should wait for completion before proceeding, therefore the submit should always occur AFTER the for loop however this does not seem to be happening.

2
  • Your single letter variables (I count ten of them) make your code more difficult to follow. Commented Mar 28, 2024 at 3:20
  • I agree. I copied an answer the link I provided. I modified it to fit in my code and was going to go back and clean it up but since it wasnt really working for me I hadn't gotten that far yet and didn't want to start changing things for no reason. Commented Mar 28, 2024 at 6:06

1 Answer 1

2

You're calling your async functions inside of non-async functions that aren't returning any promises, so you're not actually awaiting them.

func1 is async, but here it's being called inside of a non-async function that ignores the return value (Promise) of the async function:

function () { func1(); } // Calls the async func1 but doesn't await it or return the promise

This should work:

 
async function processForm() {
    //....

    async function timeout(ms) {
        return new Promise(resolve => setTimeout(resolve, ms*(Math.random() +.5)));
    }
    async function func1() {
      await page.type(...);
    }
    async function func2() {
      await page.type(...);
    }
    async function func3() {
      await page.click(...);
    }
    async function func4() {
      await page.click(...);
    }

    const array = [func1, func2, func3, func4].map(function (a, i, o) {
        var j = (Math.random() * (o.length - i) | 0) + i,
            t = o[j];
        o[j] = a;
        return t;
    });
    for (const a of array) {
        await timeout(4000);
        await a();
    }
    await timeout(4000);
    await page.click("button[type='submit']");
    
    //....
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I did not fully understand the correct syntax to make an array of async functions. (ie. I was missing the async but in your example, there is no async when defining the array. When do I need to use it?)
Think about async functions as just wrapping their return value into a Promise, and they always return Promises. A non-async function that returns a Promise, is basically the same thing as an async function. Another way to fix your original code would be just to change function () { func1(); } to function () { return func1(); }. Remember that func1 is async, so it's just like a normal function but it returns a Promise. Adding 'async' to a function just wraps its return value into a Promise that you need to either await or .then()
Thanks, that makes sense. I'm still getting use to node vs typical "sequential" languages
@eng3 - For learning purposes, your original code would have also worked if you changed this: a = function () { func1(); }, to this a = function () { return func1(); },. That way a() returns the promise that func1() returns rather than returns nothing. But, this answer is better because there's no reason to wrap func1 in another function, just put func1 directly into the array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.