Monday, July 22, 2019

How to convert a callback-based API to its async/await equivalent


Hi,

Wouldn't it be awesome, given a callback-based method that is usually invoked as below

client.get('http://myserver.com/api/resourse1', (err1, res1) => {
     if(err1) {
          console.error(err1);
     } else {
         console.log(res1.name + ' is the parent');
         client.get('http://myserver.com/api/resourse2?parent=' + res1.id, 
               (err2, res2) => {
                   if(err2) {
                        console.error(err2);
                   } else {
                       console.log(res2.name + ' is the child');
                   }
                }
     }
});

to be able to invoke it in the async/await manner?

Yes, but don't I need to refactor the method or add its "async" version? What should happen if the the API is not mine and it's a part of a third-party library?

Here is an easy and handy way to convert any callback-based third-party API to its async/await equivalent without modifying the API. Imagine the following converter:

var cb2async = (method) => async(data) => {
               return new Promise((resolve, reject)=>{
                              method(data, (err, data) => {
                                             if(err) reject(err);
                                             else resolve(data);
                              });
               });
};

By using it we can easily beautify our ugly nested code above. Here is a better code:

async mainScope() {
   try {
       var res1 = await cb2async(client.get.bind(client))
                            ('http://myserver.com/api/resourse1');
       console.log(res1.name + ' is the parent');

       var res2 = await cb2async(client.get.bind(client)) 
                            ('http://myserver.com/api/resourse2' + res1.id);
       console.log(res2.name + ' is the child');
    } catch(err) {
        console.error(err);
     }
}

Isn't that awesome? Enjoy!!!