Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I mix callbacks and async/await patterns in NodeJS?

I looked up for an answer on the internet but I could not really find what I was looking for.

I need to know what is wrong with the following code (provided we should avoid mixing callbacks and promises) -

function a(callback){
    (async ()=>{
        try{
           let result = await doSomething();
           callback(null, result);
        } catch(e){
           log('error at await');
           callback(e, null);
        }
    })()
}

Is it ok if I use the above pattern in my code?

like image 883
CodeShow Avatar asked Oct 20 '25 04:10

CodeShow


1 Answers

Can I mix callbacks and async/await patterns in NodeJS?

You can. It is not recommended.

It is generally more difficult to do proper error handling when mixing callbacks and promises. In addition, flow of control can be a real mess. This example isn't too messy because there's just one asynchronous operation, but why not just return a promise and join the modern age of asynchronous design and skip using any plain callbacks at all? Further, the await here is pretty pointless. You've just made things a lot more complicated than return doSomething() and have the caller use the returned promise.

So, you could replace 9 lines of function body (including an async IIFE) with 1 simple line.

Reasons not to mix plain callbacks and promises

  1. First, all the reasons to use promises in the first place over plain callbacks. I won't repeat all these because they have been analyzed and repeated many other times. Introducing any plain callbacks just negates a lot of the reasons for using promises in the first place.
  2. 100% Promise-based code will typically be more compact and simpler (once you know promises and how to best code them) than any mix of the two.
  3. Flow of control gets complicated real fast when you mix promises and plain callbacks. Each has a model for how to do it. Plain callbacks is much more complicated as soon as you have multiple parallel or sequenced asynchronous operations (which is why libraries such as the async library had to exist when we only had plain callbacks) whereas that level of flow control is natural and built-in with promises. Then, try mixing the two models of flow of control and error handling and things get real complicated quickly.
  4. Many developers make mistakes with error handling when trying to mix the two, failing to propagate errors back properly. The reason for these mistakes is that its just more complicated to do it right when you mix.
  5. Promises are the present and the future of asynchronous programming in Javascript/nodejs. We will even have top level await shortly and probably even asynchronous imports based on promises. Why would you add in a complication to use an old model that is no longer considered the present or future of the language.
  6. If you have some asynchronous operations that do not return promises, then you can more appropriately use them by putting a promise wrapper around them (perhaps using util.promisify()) and then using them only in their promise form for your actual implementation and control flow.
like image 120
jfriend00 Avatar answered Oct 22 '25 19:10

jfriend00