0

The following behavior of Javascript is a complete mystery to me. The following code snippet does not work:

let someFunctionOne = async () => (new Promise(resolve => setTimeout(resolve(1), 1000)))
let someFunctionTwo = async () => (new Promise(resolve => setTimeout(resolve(2), 1000)))
let someFunctionThree = async () => (new Promise(resolve => setTimeout(resolve(3), 1000)))

let myFunction = async () => {
    let resultOne
    if (true) {
        let resultTwo, resultThree // <-- doesn't work
        if (false) {
            throw new Error('Something went wrong')
        }

        const promiseOne = someFunctionOne()
        const promiseTwo = someFunctionTwo()
        const promiseThree = someFunctionThree()

        [resultOne, resultTwo, resultThree] = await Promise.all([
            promiseOne,
            promiseTwo,
            promiseThree]
        )
    resultOne = {resultOne, resultTwo, resultThree}
    }
    return resultOne
}
let result = await myFunction()
console.log(result)

This throws the following error:

ReferenceError: Cannot access 'promiseThree' before initialization

However, when the initialization of the two variables is put right above the Promise.all() call it does work:

    let someFunctionOne = async () => (new Promise(resolve => setTimeout(resolve(1), 1000)))
let someFunctionTwo = async () => (new Promise(resolve => setTimeout(resolve(2), 1000)))
let someFunctionThree = async () => (new Promise(resolve => setTimeout(resolve(3), 1000)))

let myFunction = async () => {
    let resultOne
    if (true) {
        if (false) {
            throw new Error('Something went wrong')
        }

        const promiseOne = someFunctionOne()
        const promiseTwo = someFunctionTwo()
        const promiseThree = someFunctionThree()

        let resultTwo, resultThree // <-- does work

        [resultOne, resultTwo, resultThree] = await Promise.all([
            promiseOne,
            promiseTwo,
            promiseThree]
        )
    resultOne = {resultOne, resultTwo, resultThree}
    }
    return resultOne
}
let result = await myFunction()
console.log(result)

Why on earth is the second code snippet working and the first one isn't? For both, the variable initialization of resultTwo and resultThree happen before they are used...

Thanks

Marnix.hoh
  • 1,556
  • 1
  • 15
  • 26
  • "_Does it matter where 'let' variables are initialized inside a block?_" [Yes](https://stackoverflow.com/questions/33198849/what-is-the-temporal-dead-zone). But [I can't reproduce](https://jsfiddle.net/tLgwue1v/) the error you claim with the first code. Can you provide an [mcve]? – Ivar Feb 26 '20 at 13:06
  • @Ivar See my updated answer. Thanks for your help :) – Marnix.hoh Feb 26 '20 at 14:11
  • 1
    Your issue isn't the spot where you put the `let`. It's the fact that you don't have a semicolon after the function call before that statement. See [What are the rules for JavaScript's automatic semicolon insertion (ASI)?](https://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion-asi). It is generally recommended to use semicolons, even though they are not always required by JavaScript. – Ivar Feb 26 '20 at 14:17
  • @Ivar After which function call? Where exactly should the semicolon go in the first code snippet to make it work? – Marnix.hoh Feb 26 '20 at 14:21
  • 2
    After `const promiseThree = someFunctionThree()`. Otherwise it will see the `[resultOne, resultTwo, resultThree]` as a [property accessor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors). – Ivar Feb 26 '20 at 14:21
  • @Ivar Wow that blew my mind. I was actually told that semicolons are completely optional for javascript nowadays... I guess that's not true. Thank you so much for your help – Marnix.hoh Feb 26 '20 at 14:23

0 Answers0