Prisma GraphQL-Yoga: должны ли преобразователи быть асинхронными?

#graphql #prisma #prisma-graphql

#graphql #prisma #prisma-graphql

Вопрос:

Я пытаюсь разобраться в Prisma и GraphQL, используя GraphQL-Yoga. Одна вещь, которая меня озадачила в преобразователях. В примерах Prisma (https://github.com/prisma/prisma-examples/blob/master/node/graphql/src/index.js ) вызовы DB кажутся синхронными, например

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

но я видел другие примеры, когда необходимо await возвращать данные из Prisma. Разве все эти вызовы доступа к БД не должны быть асинхронными, например

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

Ответ №1:

Во-первых, преобразователи (могут) возвращать обещание. Они не обязаны, но в обоих ваших примерах кода преобразователи возвращают обещание. Освоитесь с обещаниями, почти все асинхронные вещи в наши дни выполняются с помощью promises!

Далее вам следует прочитать об асинхронных функциях в JavaScript. async / await — это синтаксический сахар для обещаний. Как таковые, они всегда возвращают обещание (даже если вы не используете await inside).

Первый пример явно возвращает обещание. Второй пример делает то же самое, но неявно (также ожидание здесь не требуется, но это снова сделало бы его явным). Оба примера становятся более интересными, когда вы на самом деле изменяете значение впоследствии:

 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 form. Это облегчит понимание того, почему они всегда возвращают обещание и что они на самом деле делают.
После понимания этой концепции вы поймете, что оба примера на самом деле асинхронны и что await в вашем примере является необязательным (но только потому, что он следует за возвратом. Если вы посмотрите на второй пример, вы также можете понять, почему люди утверждают, что «асинхронность выглядит более синхронной»: это избавляет от обратных вызовов.

Комментарии:

1. Что также мне очень помогло, так это использование статической типизации: это заставляет меня задуматься о типе значения. Клиент Prisma также поставляется с типами для Flow и TypeScript!