4
let val = 0;

async function first() {
    console.log('1a', val);
    second();
    console.log('1b', val);
}

async function second() {
    console.log('2a', val);
    third();
    console.log('2b', val);
}

async function third() {
    console.log('3a', val);
    val = await new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve(3);
        }, 1000);
    });
    console.log('3b', val);
}

console.log('0a', val);
first();
console.log('0b', val);

I am expecting:

0a 0
1a 0
2a 0
3a 0
3b 3
2b 3
1b 3
0b 3

But I am receiving:

0a 0
1a 0
2a 0
3a 0
2b 0
1b 0
0b 0
3b 3

I'm guessing there is a fundamental thing about async which I am unaware of?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
basickarl
  • 37,187
  • 64
  • 214
  • 335
  • 2
    Only `third` is `await`ing the result of a promise, all your other functions execute synchronously. Unless you `await` `first` and `second`, they're going to return immediately. – deceze Oct 17 '16 at 14:25
  • Well, I don't know much about `await` and `async` but surely the timeout part is basically allowing the rest of the code to finish while the `await` waits for the timeout to finish? (or more specifically for the `Promise` to finish) – musefan Oct 17 '16 at 14:25
  • Wait, what version of nodejs even supports this syntax? I've tried with v6.8.1 and it throws a syntax error. – freakish Oct 17 '16 at 14:38
  • @freakish 7 with --harmony flag http://node.green/#async-functions – Yury Tarabanko Oct 17 '16 at 14:48

2 Answers2

4

You will have to await all async function calls:

async function first() {
    console.log('1a', val);
    await second();
    console.log('1b', val);
}

async function second() {
    console.log('2a', val);
    await third();
    console.log('2b', val);
}
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
3

You will need to use

async function first() {
    console.log('1a', val);
    await second();
//  ^^^^^
    console.log('1b', val);
}

async function second() {
    console.log('2a', val);
    await third();
//  ^^^^^
    console.log('2b', val);
}

to chain the b logs after the asynchronous execution of the called functions.

And it's the same for

console.log('0a', val);
first();
console.log('0b', val);

only that you cannot use await here since you are not inside an aync function. Making a function async doesn't mean that it magically blocks on everything asynchronous inside it, on the contrary - its result becomes a promise that is always asynchronous, and you can use the await keyword. So to make 0b wait, you can use either

console.log('0a', val);
first().then(function() {
    console.log('0b', val);
}, function(err) {
    console.error(err);
});

or

(async function() {
    try {
        console.log('0a', val);
        first();
        console.log('0b', val);
    } catch(err) {
        console.log(err);
    }
}());
Bergi
  • 630,263
  • 148
  • 957
  • 1,375