@withdouble/babel-plugin-promisify-async-callback v0.2.0
@withdouble/babel-plugin-promisify-async-callback
Babel plugin to promisify callback-based functions with async notation at transpilation.
Why?
async/awaitfeels great, promises not so much.- Wrapping everything in
return new Promise((resolve, reject) => { ... })is utterly redundant (to write yourself). - Sometimes, there's nothing like a good ol'callback.
Install
Install as development dependency:
yarn add --dev @withdouble/babel-plugin-promisify-async-callbackAdd this to your .babelrc file:
{
...
"plugins": [
"@withdouble/babel-plugin-promisify-async-callback"
...
]
}Usage
Write "Error-First Callback" functions (because of the existing codebase, style preference, whatever), and use them either as "errback" functions or as returning a Promise.
- Mark the function as
async - Name its last argument (the callback)
cb
You like/have callbacks...
Instead of writing
function fetchUser (userId, cb) {
api.getUser(userId, cb)
}just add async
async function fetchUser (userId, cb) {
api.getUser(userId, cb)
}and use with callbacks/promises/async/await.
...but want to get on the promise/async/await train?
Instead of writing this novel
function fetchUser (userId) {
return new Promise((resolve, reject) => {
api.getUser(userId, (error, user) => {
if (error) {
reject(error)
}
else {
resolve(user)
}
})
})
}keep it simple
async function fetchUser (userId, cb) {
api.getUser(userId, cb)
}and use with callbacks/promises/async/await.
So in the end
This function
async function fetchUser (userId, cb) {
api.getUser(userId, cb)
}can be used with callbacks
fetchUser('jdoe', (error, user) => {
...
})or promises
fetchUser('jdoe')
.then(user => { ... })
.catch(error => { ... })or async/await
try {
const user = await fetchUser('jdoe')
}
catch (error) {
...
}Gotchas :warning:
While you can use the function any way you want, you still have to write it as a callback-based function:
- Don’t
throwany error, pass them through the callbackcb(error) - Don’t
returnthe result, pass it through the callbackcb(null, result) - Don’t
await
What does it actually do?
It wraps the function body in return new Promise((resolve, reject) => { ... }) 😄
and still calls cb if one has been passed.
async function fetchUser (userId, cb) {
api.getUser(userId, cb)
}transpiles to
async function fetchUser (userId, cb) {
const fn = cb => {
api.getUser(userId, cb)
}
return new Promise((resolve, reject) => {
fn(function(err, ...args) {
if (typeof cb === 'function') {
cb(err, ...args)
}
if (err) {
reject(err)
}
else {
resolve(...args)
}
})
})
}(ok not exactly that, go check the code, it's pretty short)
8 years ago