What is the best way to wrap synchronous functions in to a promise
Solution 1
It is unclear why you would wrap a synchronous operation in a promise as that just makes it more difficult to use and synchronous operations can already be used within promise chains just fine.
The only two places I've seen it useful to make a promise out of something synchronous are to start a promise chain where subsequent operations will be async or when you are branching and one result of the branch is async promise and the other is synchronous. Then, in that case, you want to just return a promise in both cases so the caller has a consistent async interface no matter which branch is taken. Or, this could also occur with different implementations of a common API, one implementation which is synchronous and the other asynchronous. The API would be designed with an asynchronous interface and the synchronous implementation would probably wrap itself in a promise to fulfill the asynchronous contract of the common API.
Other than that, you should generally not make synchronous things async because it just unnecessarily complicates using them.
The simplest way I know of to make it into a promise would be this:
Promise.resolve(path.join(path1, path2)).then(function(path) {
// use the result here
});
Per your comments, inside a .then()
handler, exceptions are already captured by the promise infrastructure and turned into a rejected promise. So, if you had this:
someAsyncOp().then(function(value) {
// some other stuff
// something that causes an exception
throw new Error("timeout");
}).catch(function(err){
console.log(err); // will show timeout
});
Then, that exception is already mapped into a promise rejection for you. Of course, if you want to handle the exception inside of the .then()
handler (not turn the promise into a rejection), then you can just use a traditional try/catch around your synchronous operation to catch a local exception (no different than any other synchronous code). But, if you want the promise to reject if there's an exception inside the .then()
handler, then that is all done for you automatically (a very nice feature of promises).
Solution 2
Not sure if it's the best way but it works. I came to StackOverflow to check if there's a better way.
new Promise((resolve, reject) => {
try {
resolve(path.join());
} catch (err) {
reject(err);
}
})
Solution 3
Very quick way is to wrap prepend a function with async
keyword. Any async function returns a Promise
const sum = async (a, b) => a + b;
sum(1, 2).then(value => console.log(value))
s1n7ax
Updated on October 16, 2021Comments
-
s1n7ax over 2 years
Let's say I have a synchronous function like
path.join()
. I want to wrap it into aPromise
because I want exceptions to be handled withincatch()
block. If I wrap it like below, I do not get an exception in thePromise
's.catch()
block. So I have to useif
to check the return value for whether it's an error or not and then callresolve
orreject
functions. Are there any other solutions?var joinPaths = function(path1,path2) { return new promise(function (resolve, reject) { resolve(path.join(path1, path2)); }); };
-
Rodrigo Juarez almost 8 yearsWhy do you want to wrap a synchronous function into a promise?
-
Alexei Levenkov almost 8 yearsUnit testing is a common case when one needs to replace some async call with hard coded value
-
Bergi almost 8 yearsThe best way to wrap a synchronous function into a promise is not to do it.
-
Bergi almost 8 years@Srinesh: Then use
Promise.resolve().then(()=> path.join(path1, path2)).…
-
s1n7ax almost 8 years@RodrigoJuarez if im using
path.join
inside athen()
, so i can manage all exceptions in a catch block
-
-
s1n7ax almost 8 yearsIf i'm using
path.join
in promise chain and i want to handle exceptions inpromise
's.catch()
block, how can i do that with out wrapping it in to a promise? -
jfriend00 almost 8 years@Srinesh - As always, if you put your actual code and actual problem into your question, we can help you much better. I don't follow exactly what you're trying to do. A
.then()
handler in a promise chain is already wrapped in a try/catch and any exception thrown in a.then()
handler will reject the promise chain automatically. You don't have to do anything to get that functionality inside a.then()
handler. You can also use try/catch yourself to catch a synchronous exception and handle it locally. -
Daniel T. almost 7 yearsOne reason why you might want to wrap a synchronous function in a promise is if you're trying to stick to a contract, i.e.
if (needsUpdating) { return object.asyncUpdate(); } else { return object };
If one path returns a Promise, then so should the other path, even if it doesn't run any async code. -
ckot about 4 yearsI think this is along the same lines as @DanielT. mentioned, but I'm thinking it could be useful for creating an API which allows you to swap in different vendor implementations. I'm currently making a demo version of an app, where the real app uses Firestore, but I'll be using localStorage in the demo version. Even though localStorage is syncronous, I'd like to wrap with promises to make things transparent. Does this sound like a bad idea?
-
jfriend00 about 4 years@ckot - Yes, an API that will sometimes be asynchronous, must always offer an asynchronous API even if, in some cases, the implementation is not asynchronous. That would be a valid/useful reason to wrap some synchronous code in a promise.
-
ckot about 4 years@jfriend00 thx. glad to know I'm not introducing code smell by doing that.