Search code examples
javascriptobjectasync-awaitswitch-statementobject-literal

Can't access object key in async function when using Object-literals and switch-case, What am i doing wrong?


here I tried to get a value from the function in this case my function return an object, When i try to access it with key I get "undefined" as bar1 but bar2 It's has values of a object.

const foo = async()=> {
    let zoo
    let data = [
        {
            key1:"1",
            key2:"a",
            key3:3,
            key4:"cal",
        }
    ]
    
    for (const iterator of data) {
        // console.log(iterator)
            bar1 = {
                objectLiteral_swithAsync:  await objectLiteral_swithAsync(iterator["key4"]).exe1,
                objectLiterals_withOutAsync :   objectLiterals_withOutAsync(iterator["key4"]).exe1,
                switch_WithAsync : await switch_WithAsync(iterator["key4"]).exe1,
                switch_WithOutAsync :  switch_WithOutAsync(iterator["key4"]).exe1,
            }
            bar2 ={
                objectLiteral_swithAsync:  await objectLiteral_swithAsync(iterator["key4"]),
                objectLiterals_withOutAsync :   objectLiterals_withOutAsync(iterator["key4"]),
                switch_WithAsync : await switch_WithAsync(iterator["key4"]),
                switch_WithOutAsync :  switch_WithOutAsync(iterator["key4"]),
            }
            zoo = {

                bar1 :bar1,
                bar2: bar2
            }
    }
    return zoo
}

async function objectLiteral_swithAsync(param) {

    let obj=  {
       
        'cal': 2 * 2
    }[param]
    let result = {
        exe1 : obj,
        exe2: 2
    }
    return result
}

 function objectLiterals_withOutAsync(param) {
    
    let obj=  {
      
       'cal': 2 * 2
    }[param]
    let result = {
        exe1 : obj,
        exe2: 2
    }
    
    return result
}
async function switch_WithAsync (param){
    let obj
    switch (param) {
        case "cal":
            obj = 2 * 2
            break;
    
        default:
            obj =0
            break;
            
    }
     result = {
        exe1 : obj,
        exe2: 2
    }
    return result
}

function switch_WithOutAsync  (param){
    let obj
    switch (param) {
        case "cal":
            obj = 2 * 2
            break;
    
        default:
            obj =0
            break;
    }
     result = {
        exe1 : obj,
        exe2: 2
    }
    return result
}

foo().then( result=>{
    console.log('--->1',result)
})
// console.log('2', foo())

the result in object bar1 are undefined when its called asyncfunction with the . notation but in bar2 every keys has a value.


Solution

  • Promises don't have a .exe1 property, yet your code is trying to retrieve such property from a promise object.

    In this expression:

     await objectLiteral_swithAsync(iterator["key4"]).exe1
    

    ...the order of evaluation is as follows:

    1. iterator["key4"] evaluates to "cal"
    2. objectLiteral_swithAsync(iterator["key4"]) evaluates to a promise (an async function returns a promise)
    3. <a promise>.exe1 evaluates to undefined as it accesses a non-existing property
    4. await undefined will suspend the function to be resumed asynchronously, and then this evaluates to undefined

    What you really want, is to have the .exe1 access to happen when you already have awaited the promise and have the value it fulfilled with. So change the order of execution with parentheses:

     (await objectLiteral_swithAsync(iterator["key4"])).exe1
    

    Now the order of evaluation is as follows:

    1. iterator["key4"] evaluates to "cal"
    2. objectLiteral_swithAsync(iterator["key4"]) evaluates to a promise.
    3. await <promise> suspends the function until the promise is resolved. When it resumes asynchronously, this expression evaluates to {exe1: 4, exe2: 2}
    4. ({exe1: 4, exe2: 2}).exe1 evaluates to 4

    const foo = async()=> {
        let zoo;
        let data = [{
            key1:"1",
            key2:"a",
            key3:3,
            key4:"cal",
        }];
        
        for (const iterator of data) {
            const bar1 = {
                objectLiteral_swithAsync: (await objectLiteral_swithAsync(iterator["key4"])).exe1,
                objectLiterals_withOutAsync: objectLiterals_withOutAsync(iterator["key4"]).exe1,
                switch_WithAsync: (await switch_WithAsync(iterator["key4"])).exe1,
                switch_WithOutAsync: switch_WithOutAsync(iterator["key4"]).exe1,
            };
            const bar2 = {
                objectLiteral_swithAsync: await objectLiteral_swithAsync(iterator["key4"]),
                objectLiterals_withOutAsync: objectLiterals_withOutAsync(iterator["key4"]),
                switch_WithAsync: await switch_WithAsync(iterator["key4"]),
                switch_WithOutAsync: switch_WithOutAsync(iterator["key4"]),
            };
            zoo = {
                bar1,
                bar2
            };
        }
        return zoo;
    }
    
    async function objectLiteral_swithAsync(param) {
        const obj = {       
            cal: 2 * 2
        }[param];
        const result = {
            exe1: obj,
            exe2: 2
        }
        return result;
    }
    
    function objectLiterals_withOutAsync(param) {
        const obj = {      
           cal: 2 * 2
        }[param];
        const result = {
            exe1 : obj,
            exe2: 2
        };
        return result;
    }
    
    async function switch_WithAsync (param){
        let obj;
        switch (param) {
            case "cal":
                obj = 2 * 2;
                break;
            default:
                obj = 0;
                break;
        }
        const result = {
            exe1: obj,
            exe2: 2
        }
        return result;
    }
    
    function switch_WithOutAsync  (param){
        let obj;
        switch (param) {
            case "cal":
                obj = 2 * 2;
                break;
            default:
                obj = 0;
                break;
        }
        const result = {
            exe1: obj,
            exe2: 2
        };
        return result;
    }
    
    foo().then(result => {
        console.log('--->1', result)
    });