Reputation: 5781
I often see in other peoples docs something like:
Callback is optional, if omitted returns a promise.
This is what I have:
export function doSomeAsync(options, callback) {
const useCallback = (callback && typeof callback == 'function');
const promise = new Promise((resolve, reject) => {
// --- do async stuff here ---
const check = (options.num === 1) ? true : false;
setTimeout(() => {
if (check) {
finish(true, "Number is 1");
} else {
finish(false, new Error("Number is not 1"));
}
}, 1000);
// ---------------------------
function finish(ok, rtn) {
if (useCallback) {
if (ok) {
callback(null, rtn);
} else {
callback(rtn, null);
}
} else {
if (ok) {
resolve(rtn);
} else {
reject(rtn);
}
}
}
});
return (useCallback) ? false : promise;
}
The finish()
function just avoids lots of if...
statements scattered around.
I'm creating a promise object, whether or not I use it.
Testing like this:
doSomeAsync({ num: 1 }).then((result) => {
console.log('p result', result);
}).catch((err) => {
console.log('p err', err);
});
doSomeAsync({ num: 1 }, (err, result) => {
if (err) {
console.log('cb err', err);
} else {
console.log('cb result', result);
}
});
This works, but I'm wondering if this is the best way, or if others have a better and more succinct implementation..?
Upvotes: 14
Views: 4994
Reputation: 1489
You could get rid of all edge cases by always returning a promise, and define a default callback (a callback-shaped identity function) that handles the no-callback-supplied case:
const genericAsync = (stuff, callback = (e, i) => e || i) => new Promise(
(resolve, reject) => doStuffWith(stuff, resolve, reject)
)
.then(response => callback(null, response))
.catch(callback);
Upvotes: 1
Reputation: 522109
This could be simplified if you simply always used the promise, which you're always creating anyway:
export function doSomeAsync(options, callback) {
const promise = new Promise((resolve, reject) => {
const check = (options.num === 1) ? true : false;
setTimeout(() => {
if (check) {
resolve("Number is 1");
} else {
reject(new Error("Number is not 1"));
}
}, 1000);
});
if (callback && typeof callback == 'function') {
promise.then(callback.bind(null, null), callback);
}
return promise;
}
Your function is always promise-based, also in the fact that it always returns a promise. The caller is simply free to ignore that. The callback argument is merely a "legacy fallback interface" (or "alternative interface" if you prefer) to using that promise.
Upvotes: 24