The prisma client has what it calls a "fluent" API, which allows you to chain requests for sub-types but work with them all as if they were a promise (docs). Example:
const organization = await prisma.schedule({id: "foo"{}).organization();
All of the examples in the documentation demonstrate using async
/await
syntax when working with the client. Inspecting what gets returned from a call to the client shows then
and catch
properties, like a normal promise, as well as the other fields exposed as functions (which is what allows the fluent API).
The Problem
The ReasonML bindings I've written assume normal JavaScript promise behavior - async
/await
isn't supported in Reason. When encountering a Prisma error, however, my code wasn't actually handling the error like I'd expect - in fact, the catch
function wasn't called.
Here's the generated output from the Reason Compiler (Repromise
is a 3rd party lib that makes promises easier to work with in Reason. In this case match[0]
is a promise getting returned from the function, and match[1]
is the resolve
function to resolve that promise. Essentially we're creating a new promise and returning it, and resolving it inside the handlers for Prisma's promise.)
function create$2(input) {
var match = Repromise.make(/* () */ 0);
var resolve = match[1];
PrismaClient.prisma
.schedule(input)
.then(function(res) {
return Promise.resolve(
Curry._1(resolve, /* Ok */ Block.variant("Ok", 0, [res])),
);
})
.catch(function(err) {
debugger;
return Promise.resolve(
Curry._1(resolve, /* Error */ Block.variant("Error", 1, [err])),
);
});
return match[0];
}
This code has an intentional error in it (the input being passed is for creating a schedule, not querying for one) and so Prisma returns an error... but the catch
block is never executed, and the debugger
statement is never hit.
If I manually edit the compiled output to use async
/await
, it works as expected:
async function create$2(input) {
var match = Repromise.make(
/* () */
0);
var resolve = match[1];
debugger;
try {
const res = await PrismaClient.prisma.schedule(input);
Curry._1(resolve,
/* Ok */
Block.variant("Ok", 0, [res]));
} catch (err) {
debugger;
Curry._1(resolve,
/* Error */
Block.variant("Error", 1, [err]));
}
return match[0];
}
In this case, the debugger
is triggered and the error is reported correctly.
I'm thinking that something about the way Prisma's client is modifying a base Promise to extend it with the additional fields must somehow be affecting normal Promise behavior?