Improved way to deal with callbacks inside promises
Improved way to deal with callbacks inside promises
I have the following code that uses callbacks
inside promises
:
callbacks
promises
const clue = 'someValue';
const myFunction = (someParam, callback) =>
someAsyncOperation(someParam) // this function returns an array
.then((array) =>
if (array.includes(clue))
callback(null, array); // Callback with 'Success'
else
callback(`The array does not includes: $clue`); // Callback with Error
)
.catch((err) =>
// handle error
callback(`Some error inside the promise chain: $err`) // Callback with Error
)
and call it like this:
myFunction (someParam, (error, response) =>
if(error)
console.log(error);
else
// do something with the 'response'
)
Reading some documentation, I found that there is some improved way to do this:
const myFunction = (someParam, callback) =>
someAsyncOperation(someParam) // this function returns an array
.then((array) =>
if (array.includes(clue))
callback(array);
else
callback(`The array does not includes: $clue`);
, (e) =>
callback(`Some error happened inside the promise chain: $e`);
)
.catch((err) =>
// handle error
callback(`Some error happened with callbacks: $err`)
)
My question:
In the sense of performance or best practices, it's okay to call the 'callback' function
inside the promise as the two ways show or I'm doing something wrong, I mean some promise anti-pattern way ?
'callback' function
.then
catch
catch
Also note that your second code, during success, is calling
callback
with array
as the first argument (the error
) rather than the second argument (the response
).– CertainPerformance
Sep 2 at 23:25
callback
array
error
response
Don't use callbacks inside of promises - that is an anti-pattern. Just return a promise and let the promise handle the notificaiton of completion or error. That's what they are designed for. The caller will then use
.then()
and .catch()
on the returned promise instead of a callback. This is the current state and future of Javascript.– jfriend00
Sep 2 at 23:45
.then()
.catch()
Don't unpromisify!
– Roamer-1888
Sep 3 at 1:00
@robe007 - Per your request, I added an answer to illustrate.
– jfriend00
Sep 3 at 2:39
2 Answers
2
This seems really backwards and takes away from the benefits of promises managing errors and passing them down the chain
Return the asynchronous promise from the function and don't interrupt it with callbacks. Then add a catch at the end of the chain
const myFunction = (someParam) =>
// return the promise
return someAsyncOperation(someParam) // this function returns an array
.then((array) =>
return array.includes(clue) ? array : ;
);
myFunction(someParam).then(res=>
if(res.length)
// do something with array
else
// no results
).catch(err=>console.log('Something went wrong in chain above this'))
This answer and
jfriend00's
answer are very good explained, but I select this becasue was the first. I can say that today I have learned again !– robe007
Sep 3 at 4:21
jfriend00's
Do not use callbacks from inside of promises, that is an anti-pattern. Once you already have promises, just use them. Don't "unpromisify" to turn them into callbacks - that's moving backwards in code structure. Instead, just return the promise and you can then use .then()
handlers to set what you want the resolved value to be or throw an error to set what you want the rejected reason to be:
.then()
const clue = 'someValue';
const myFunction = (someParam) =>
return someAsyncOperation(someParam).then(array =>
if (!array.includes(clue))
// reject promise
throw new Error(`The array does not include: $clue`);
return array;
);
Then, the caller would just do this:
myFunction(someData).then(array =>
// success
console.log(array);
).catch(err =>
// handle error here which could be either your custom error
// or an error from someAsyncOperation()
console.log(err);
);
This gives you the advantage that the caller can use all the power of promises to synchronize this async operation with any others, to easily propagate errors all to one error handler, to use await
with it, etc...
await
It is possible also to add a
catch
statement to someAsyncOperation
right?– robe007
Sep 3 at 3:28
catch
someAsyncOperation
@robe007 - Yes, but there is no need unless you want to "handle" that error locally and not let the caller see that error directly. If the
someAsyncOperation()
promise rejects, then your .then()
will not be called and the caller will directly see the rejected promise and their own .catch()
which they already need to have will see the error.– jfriend00
Sep 3 at 3:41
someAsyncOperation()
.then()
.catch()
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Pretty sure you should not have both an error handler (as the second argument to
.then
) and acatch
. It's probably better to have only a singlecatch
.– CertainPerformance
Sep 2 at 23:23