Prisma GraphQL-Yoga:解析器是否需要异步?

Prisma GraphQL-Yoga: do the resolvers need to be asynchronous?

我正在尝试使用 GraphQL-Yoga 来研究 Prisma 和 GraphQL。让我对解析器感到困惑的一件事。在 Prisma 示例 (https://github.com/prisma/prisma-examples/blob/master/node/graphql/src/index.js) 中,数据库调用似乎是同步的,例如

 Mutation: {
    signupUser: (parent, { email, name }, context) => {
      return context.prisma.createUser({
        email,
        name,
      })
    },

但我见过其他示例,其中必须 await 来自 Prisma 的 return。不应该所有这些数据库访问调用都是异步的,比如

 Mutation: {
        signupUser: async (parent, { email, name }, context) => {
          return await context.prisma.createUser({
            email,
            name,
          })
        },

首先,解析器(可以)return 一个承诺。他们不必这样做,但在您的两个代码示例中,解析器 return 都是一个承诺。对 promises 感到舒服,现在几乎所有异步的事情都是用 promises 完成的!

接下来您应该阅读 JavaScript 中的异步函数。 async/await 是 promise 的语法糖。因此他们总是 return 一个承诺(即使你不在里面使用 await)。

第一个示例 return 是一个明确的 Promise。第二个例子做同样的事情但隐含地(这里也不需要 await 但这会再次明确)。当您之后实际修改值时,这两个示例都会变得更有趣:

signupUser: (parent, { email, name }, context) => {
  return context.prisma.createUser({
    email,
    name,
  }).then(user => {
    return { ...user, isCool: user.friends > 5 };
  });
}
// vs. async function
signupUser: async (parent, { email, name }, context) => {
  const user = await context.prisma.createUser({
    email,
    name,
  };
  return { ...user, isCool: user.friends > 5 };
}

句法糖意味着它背后没有实际的新语言特性。通常,编译器在编译语法之前首先对其进行脱糖(尤其是在函数式语言中)。作为一种心智模型,您可以想象将异步函数重写为 promise 形式。这将使人们更容易理解为什么他们总是 return 承诺以及他们实际在做什么。 掌握了这个概念后,您将了解这两个示例实际上都是异步的,并且示例中的 await 是可选的(但只是因为它遵循 return。如果您查看第二个示例,您可能还会看看为什么人们声称 "async looks more syncronous":它摆脱了回调。