0

如果您将修改后的上下文传递给 GraphQL 解析器,这是否会传播到所有下游解析器?这是在 GraphQL 规范中指定的还是特定于实现的?

为了澄清一个例子说我有一个像下面这样的查询

{
  companies {
    employees {
      positions {
        title
      }
    }
  }
}

假设我从contextA进入companies查询开始,然后我CompanyResolvers得到了我的位置superSpecialContext并将其传递给employees数据加载器

export const CompanyResolvers = {
    employees: async ({ id }: CompanyDTO, args: object, contextA: Context) => {
      const superSpecialContext = await getSuperSpecialContext();
      return context.dataLoaders.employees.load({ id: company.id, context: superSpecialContext });
    }
};

当我到达positions解析器时,我现在是在使用superSpecialContext原版还是原版contextA(我实际上更喜欢这种情况)?

export const EmployeeResolvers = {
    positions: async ({ id }: EmployeeDTO, args: object, context: Context) => {
      // is my context here contextA or superSpecialContext?
    }
};
4

1 回答 1

2

如果您将修改后的上下文传递给 GraphQL 解析器,这是否会传播到所有下游解析器。

是的,每个请求在请求期间都有自己的上下文对象。它是在 GraphQL 服务器上的上下文函数中创建的。

import { ApolloServer, gql } from 'apollo-server'
import { ExpressContext } from 'apollo-server-express/dist/ApolloServer';

const typeDefs = gql`
  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
  }
`;

const books = [
  {
    title: 'Harry Potter and the Chamber of Secrets',
    author: 'J.K. Rowling',
  },
  {
    title: 'Jurassic Park',
    author: 'Michael Crichton',
  },
];

const resolvers = {
  Query: {
    books: (obj: any, args: any, context: any) => {
      console.log(context.name);  // Khalil Stemmler
      context.name = 'Billy Bob Thorton'
      return books;
    },
  },
  Book: {
    title: (obj: any, args: any, context: any) => {
      console.log(context.name); // Billy Bob Thorton.
      // Should print "Billy Bob Thorton twice", once for each book.
      return obj.title
    },
  }
};

const server = new ApolloServer({ 
  typeDefs, 
  resolvers,
  context: (expressContext: ExpressContext) => {
    // The Apollo implementation of context allows you hook into the
    // Express request to get access to headers, tokens, etc- in order 
    // to grab an authenticated user's session data and put it on context.
    const { connection, res, req } = expressContext;

    // A new context object is created for every request. This function
    // should return an object.
    return {
      name: 'Khalil Stemmler'
    }
  }
});

// The `listen` method launches a web server.
server.listen().then(({ url }: { url: string }) => {
  console.log(`  Server ready at ${url}`);
});

运行以下查询:

{
  books {
    title
    author
  }
}

我们得到:

  Server ready at http://localhost:4000/
Khalil Stemmler
Billy Bob Thorton
Billy Bob Thorton

参考:“上下文参数 - Apollo Docs ”。

于 2019-12-12T03:30:41.637 回答