代码之家  ›  专栏  ›  技术社区  ›  Evanss

Apollo链接状态仅在定义了冗余查询时有效?

  •  1
  • Evanss  · 技术社区  · 6 年前

    我让阿波罗链接州工作:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { HttpLink, InMemoryCache, ApolloClient } from 'apollo-client-preset';
    import { WebSocketLink } from 'apollo-link-ws';
    import { ApolloLink, split } from 'apollo-link';
    import { getMainDefinition } from 'apollo-utilities';
    import { AUTH_TOKEN } from './constant';
    import RootContainer from './components/RootContainer';
    import { ApolloProvider } from 'react-apollo';
    import { withClientState } from 'apollo-link-state';
    import { gql } from 'apollo-boost';
    
    const httpLink = new HttpLink({ uri: 'http://localhost:4000' });
    
    const middlewareLink = new ApolloLink((operation, forward) => {
      const tokenValue = localStorage.getItem(AUTH_TOKEN);
      operation.setContext({
        headers: {
          Authorization: tokenValue ? `Bearer ${tokenValue}` : '',
        },
      });
      return forward(operation);
    });
    
    const httpLinkAuth = middlewareLink.concat(httpLink);
    
    const wsLink = new WebSocketLink({
      uri: `ws://localhost:4000`,
      options: {
        reconnect: true,
        connectionParams: {
          Authorization: `Bearer ${localStorage.getItem(AUTH_TOKEN)}`,
        },
      },
    });
    
    const link = split(
      ({ query }) => {
        const { kind, operation } = getMainDefinition(query);
        return kind === 'OperationDefinition' && operation === 'subscription';
      },
      wsLink,
      httpLinkAuth,
    );
    
    const cache = new InMemoryCache();
    
    const stateLink = withClientState({
      cache,
      defaults: {
        groupMenuStatus: {
          __typename: 'GroupMenuStatus',
          isOpen: false,
        },
      },
      resolvers: {
        Mutation: {
          updateGroupMenuStatus: (_, { isOpen }, { cache }) => {
            const data = {
              groupMenuStatus: {
                __typename: 'GroupMenuStatus',
                isOpen,
              },
            };
            cache.writeData({ data });
            return null;
          },
        },
        Query: {
          groupMenuStatus: async (_, args, { cache }) => {
            const query = gql`
              query groupMenuStatus {
                groupMenuStatus @client {
                  isOpen
                }
              }
            `;
            const res = cache.readQuery({ query });
            return res.groupMenuStatus;
          },
        },
      },
    });
    
    const client = new ApolloClient({
      link: ApolloLink.from([stateLink, link]),
      cache,
      connectToDevTools: true,
    });
    
    const token = localStorage.getItem(AUTH_TOKEN);
    
    ReactDOM.render(
      <ApolloProvider client={client}>
        <RootContainer token={token} />
      </ApolloProvider>,
      document.getElementById('root'),
    );
    

    然而,大多数在线示例不需要定义查询解析器。如果我删除下面的代码,那么来自前端的查询将始终返回默认状态,该变异似乎没有效果:

    Query: {
          groupMenuStatus: async (_, args, { cache }) => {
            const query = gql`
              query groupMenuStatus {
                groupMenuStatus @client {
                  isOpen
                }
              }
            `;
            const res = cache.readQuery({ query });
            return res.groupMenuStatus;
          },
        },
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   marcelotokarnia    6 年前

    根据官方文件 https://www.apollographql.com/docs/link/links/state.html

    Query resolvers are only called on a cache miss. Since the first time you call the query will be a cache miss, you should return any default state from your resolver function.

    因此,如果定义了默认值,则永远不会调用查询解析器。(你的定义是对的,它叫做 Query 确实如此)

    如果不声明默认值,则可以使用查询解析器在缓存中写入内容(然后将不再调用查询解析器),或者只返回一些值,每次都将调用解析器。

    例如,我使用它在第一次调用时获取用户地理位置,这是我现在的默认值,并且永远不会再次调用解析器。

    检查我的用例:

    Query: {
        async smePosition(_: any, {}: any, { cache }: IContext): Bluebird<any> {
          return new Bluebird((resolve: any, reject: any): void => {
            window.navigator.geolocation.getCurrentPosition(
              ({coords: {latitude: lat, longitude: lng}}) => {
                const data = {
                  smePosition: {
                    __typename: 'SMe',
                    position: {lat, lng , __typename: 'IPosition'},
                  },
                }
                cache.writeData({ data })
                resolve()
              },
            )
          })
        },
      },
    

    在这种情况下,我不为“smePosition”定义默认值