0

In a function run1 random value is generated & stored in random_var, await is used to delay and then random_value is resolved.

When running run1 asynchronously using Promise.all the random_var is changed when logging after await statement as shown in the code snippet demo

main()

async function main() {
    await Promise.all([run1(), run1(), run1()]).then(value => {
        console.log({ values: value })
    })
}

async function run1() {
    return new Promise(async (resolve, reject) => {
        random_var = makeid(6)
        console.log('Logging 1st time has different values', random_var)
        await new Promise(resolve => setTimeout(resolve, 500))
        console.log('Logging 2nd time has same values', random_var)
        resolve(random_var)
    })
}


function makeid(length) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}
Abrar Ahmed
  • 124
  • 1
  • 3
  • 14
  • On an async programming note: try not to mix `async/await` with manually building `new Promise`. An `async` by definition returns a Promise, with the async function's return automatically causing Promise resolution. `fn = async () { return 4; }` behaves the same as `fn = () => new Promise(resolve => resolve(4));`. – Mike 'Pomax' Kamermans Nov 02 '19 at 18:07
  • 3
    Just don't use global variables -> `const random_var` – Andreas Nov 02 '19 at 18:09
  • Always use strict mode! It would have thrown when you tried to assign the undeclared variable. – Bergi Nov 02 '19 at 18:12
  • @Mike'Pomax'Kamermans It's fine to use `new Promise` for promisification of e.g. `setTimeout` in conjunction with `await`, but indeed one should [never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572). – Bergi Nov 02 '19 at 18:13
  • sure, but if you're mixing asynchronous code with setTimeout, I probably have other questions about why you think you need "at least but absolutely not guaranteed to be X ms" deferral. – Mike 'Pomax' Kamermans Nov 02 '19 at 18:18

1 Answers1

1

This has to do with hoisting and scope. You line random_var = makeid(6) doesn't use let or const so it gets hoisted to the global scope where it will not change when the promises resolve. changing it to const random_var = makeid(6) (or let or var, but best practice is const here because you're not going to ever mutate it) should resolve the issue.

main()

async function main() {
    await Promise.all([run1(), run1(), run1()]).then(value => {
        console.log({ values: value })
    })
}

async function run1() {
    return new Promise(async (resolve, reject) => {
        const random_var = makeid(6)
        console.log('Logging 1st time has different values', random_var)
        await new Promise(resolve => setTimeout(resolve, 500))
        console.log('Logging 2nd time has same values', random_var)
        resolve(random_var)
    })
}


function makeid(length) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}
bdbdbd
  • 416
  • 5
  • 13