Chris Mitchell Online

Chris blogging about cloud, IT, and programming. What could go wrong?

Quick Promises with NodeJS

2019-05-17

Typically in NodeJS version 7.6 and later instead of using promise chaining and callback functions, or as this is commonly referred to as callback hell we can now use async and await. In this article I’ll show you my two favorite go-to patterns to utilize Promises in Javascript.

A Quick Primer

Prior to NodeJS version 7.6 when writing code that involved Javascript Promises, or code that I needed to know when it succeeded or failed, I would typically utilize an anonymous callback function using the following syntax:

myFunction(){
    methodThatReturnsPromise(function(){
        //this the callback function that gets called when the 
        //function "methodThatReturnsPromise" resolves its promise.
    })
}

This code, while quick and dirty would get the job done. But now how do we know when myFunction is finished? How do we wait on everything it needs to do first? We would have to introduce another callback. Hence the callback hell reference. Just to mention, It’s hard to follow. Enter async and await

Async and Await

Taking our previous code example, we can now convert this into async and await syntax:

async myFunction(){
    let expectedEndValue = await methodThatReturnsPromise();
    //Execute code now that would have been in a callback function before.
    //Instead, expectedEndValue is now ready to go because of await.
}

Much cleaner, and easier to follow. Simply await what we need to know happens, and continue with our execution of code based on that response.

Pattern 1: Dedicated Promise Method

My first go-to pattern is to use a dedicated method in a class that returns a promise, and await the results in the calling methods. Take this class for example, where I utilize the AWS SDK for NodeJS to retrieve S3 data. The method publicGetS3Object is async, so I can await the results of the retrieveS3Data, and perform actions on the S3 data when its done.

const AWS = require("aws-sdk");

class S3DataService {

    constructor(){
        this.s3=new AWS.S3();
    }

    async publicGetS3Object(objectToGet){
        let s3Data = await this.retrieveS3Data(objectToGet);        
        /*
        Perform actions on S3 data when its done.
        */
    }

    retrieveS3Data(object){
        var params = {
            Bucket: "example.bucket", 
            Key: object,            
        };
        return this.s3.getObject(params).promise();
    }
}

Pattern 2: Inline Promises

The dedicated method pattern is great for reusability, and MOST of the time I use the pattern outlined earlier in this article, but what if your code only needs to perform one action that needs to resolve a promise, and move on? And this one action will only happen one time, so no other methods will need to utilize a service, in this case we can use an inline promise.

We know that with await we can wait for a promise to resolve then continue on. Here is the same code without a service method:

async inlinePromise(object){                
    let s3= new AWS.S3();

    var params = {
        Bucket: "blog.chrismitchellonline.com", 
        Key: object            
    };

    let S3Data = await s3.getObject(params).promise();
    return S3Data;
}

Bonus Inline Promise

Here is an example of an inline Javascript Promise I’ve used to send calls to AWS Lambda:

let params={
    FunctionName: 'microservice',
    InvocationType: 'RequestResponse',
    LogType: 'Tail',
    Payload: JSON.stringify(payload),
    Qualifier: 'DEV'
}
let lambda=new AWS.Lambda();
    
let lambdaCall= new Promise(function(resolve,reject){
    lambda.invoke(params,function(err,data){
        if(err){
            let errorMsg="Error sending cancel to Ship Compliant Lambda service"
            console.log(errorMsg)
            console.log(err);
            reject(errorMsg);                        
        }                    
        resolve(data);
    }) 
})
await lambdaCall;
return;

Normally we can send calls to Lambda asynchronous, but I needed to have that Lambda call finish before continuing with this script, and there is the beauty of async and await.

Conclusion

As long as you are using NodeJS 7.6 and above it is fairly easy to avoid callback confusion and promise chaining using async and await. The examples I’ve shown today are simple, but show how much less confusing using promises can be. Please leave any comments about this article below, and give me an Upvote if you liked the article.

References

comments powered by Disqus