Edit - While the answers contain a couple of viable solutions, I'll point out that Parse JS SDK 2.0 (and thus Parse-Server 3.0) have been announced, and actually remove Parse.Promise. So, the best solution would be to swap out Parse Promise implementations and use native Promises instead.
I use Parse-Server ( latest version, 2.8.2 ) as a backend. I got very used to promises, and they are heavily ingrained in my code.
I've been starting to use the async / await pattern instead, though. But it isn't playing nicely with all of my existing implementations.
This example will throw an error:
const promiseErrorTestHelper = async () => {
return Parse.Promise.as();
}
Parse.Cloud.define('promiseErrorTest', async(req, res) => {
promiseErrorTestHelper().always(
res.success
);
});
This one works fine:
const promiseErrorTestHelper = async () => {
return Parse.Promise.as();
}
Parse.Cloud.define('promiseErrorTest', async(req, res) => {
promiseErrorTestHelper().then(
res.success
);
});
In Parse-Server, .always()
is used to pass a callback function whether the promise was rejected or resolved. I have used this throughout my code, and discovered the issue while refactoring some functions to use async / await while adding new functionality.
I understand the issue to be that async functions wrap their result in a promise. So, it's taking my Parse.Promise
and converting it to a different type that does not have the .always()
method.
Is there by chance a simple way for me to override the functionality of async to return a Parse.Promise instead? Or will I have to rework the always()
calls if I want to use async / await?
It appears that you cannot change what type of promise is returned from an async
function. It is built-in to return a native promise and is not configurable. There's a similar discussion here about how to make an async
function return a Bluebird promise here. The conclusion was that you can't so if you want a Bluebird promise, you have to wrap the async
function.
To continue after an error, the usual way is to use a .catch()
that logs the error and doesn't rethrow, thus "handling" the error:
someFunc().catch(err => {
// handle the error, continue processing, changes promise chain to resolved
console.log(err);
return null;
}).then(() => {
// will always get called when original promise resolves or rejects
// somewhat like your .always
});
Or, you can wrap your async functions to return your desired type of promise:
function wrapFunc(arg) {
return Parse.Promise.resolve(someAsyncFunc(arg))
}
And, then call the wrapper function instead.
I'm not sure I recommend this because you are modifying the globally accessible Promise prototype which could affect other code, but you could also add a .always()
to the built-in promise.
Promise.prototype.always = function(fn) {
return this.then(fn, fn);
}
Which is actually the exact same implementation that Parse uses. Then, you can use .always()
on promises returned from async
functions.