0

I am bit confused about the Promise chaining in AWS Lambda.

exports.handler = async (event) => {
firstMethod = ()=>{
    return new Promise(function(resolve, reject){
        setTimeout(function() {
            resolve({data: '123'})
        }, 2000);
    });

}
secondMethod = (someStuff)=>{
    return new Promise(function(resolve, reject){
        setTimeout(function() {
            resolve({newData:someStuff.data + ' some more data'})
        }, 2000);
    });

}
return new Promise((resolve, reject)=>{
        firstMethod().
        then((data)=>{
            console.log("firtMethod data ",JSON.stringify(data));
            secondMethod(data);
        }).
        then((data)=>{
            console.log("second Method data",JSON.stringify(data));
            resolve("final data",data);
        });

    });
    
}

I am expecting above code to get output of the firstMethod first and then secondMethod. But i am getting second method data as undefined.

Naveen Kerati
  • 951
  • 3
  • 13
  • 29

1 Answers1

2

The main problem is that your fulfillment handler on the promise from firstMethod doesn't return anything. If you want it to return the promise from secondMethod so that the chain waits on that promise, you need to do that explicitly:

firstMethod().
then((data)=>{
    console.log("firtMethod data ",JSON.stringify(data));
    return secondMethod(data);
//  ^^^^^^
}).
then((data)=>{
    console.log("second Method data",JSON.stringify(data));
    resolve("final data",data);
});

But, there are some other things you should probably fix as well.

First, you haven't declared either firstMethod or secondMethod, which means that code is falling prey to what I call The Horror of Implicit Globals. Declare your variables.

Second, you're passing more than one argument to resolve:

resolve("final data",data);

resolve ignores all arguments except the first one.

Third, your code is using the promise creation anti-pattern. You already have a promise from firstMethod, you don't need to create a new promise. Just chain off the one you already have.

Instead of:

return new Promise((resolve, reject)=>{
    firstMethod().
    then((data)=>{
        console.log("firtMethod data ",JSON.stringify(data));
        return secondMethod(data);
    }).
    then((data)=>{
        console.log("second Method data",JSON.stringify(data));
        resolve("final data",data);
    });
});

in a non-async function you'd use:

return firstMethod().
    then((data)=>{
        console.log("firtMethod data ",JSON.stringify(data));
        return secondMethod(data);
    }).
    then((data)=>{
        console.log("second Method data",JSON.stringify(data));
        return "final data");
    });

This also has the advantage of ensuring that rejections are passed back to the caller for the caller to handle.

But, since your wrapper function is an async function, you can use await instead of explicitly consuming the promises:

exports.handler = async (event) => {
    const firstMethod = ()=>{
        return new Promise(function(resolve, reject){
            setTimeout(function() {
                resolve({data: '123'})
            }, 2000);
        });
    };
    const secondMethod = (someStuff)=>{
        return new Promise(function(resolve, reject){
            setTimeout(function() {
                resolve({newData:someStuff.data + ' some more data'})
            }, 2000);
        });
    };
    const data = await firstMethod();
    console.log("firtMethod data ",JSON.stringify(data));
    await secondMethod(data);
    console.log("second Method data",JSON.stringify(data));
    return "final data";
};
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875