2

我正在创建一个这样的 Apollo 客户端:

var { ApolloClient }    = require("apollo-boost");
var { InMemoryCache }   = require('apollo-cache-inmemory');
var { createHttpLink }  = require('apollo-link-http');
var { setContext }      = require('apollo-link-context');

exports.createClient = (shop, accessToken) => {

  const httpLink = createHttpLink({
    uri: `https://${shop}/admin/api/2019-07/graphql.json`,
  });
  const authLink = setContext((_, { headers }) => {
    return {
      headers: {
        "X-Shopify-Access-Token": accessToken,
        "User-Agent": `shopify-app-node 1.0.0 | Shopify App CLI`,
      }
    }
  });  

  return new ApolloClient({
    cache: new InMemoryCache(),
    link: authLink.concat(httpLink),
  });
};

点击 Shopify GraphQL API,然后运行如下查询:

    return client.query({
        query: gql` {
            productVariants(first: 250) {
                edges {
                    node {
                        price
                        product {
                            id
                        }
                    }
                    cursor
                }
                pageInfo {
                    hasNextPage
                }
            }
        }
    `})

但是返回的对象只包含数据而没有扩展,这对于计算查询的实际成本是一个问题。

知道为什么吗?

非常感谢您的帮助

4

2 回答 2

1

有一些我们之前写过的 hacky 方法:

您需要创建一个自定义的 apollo 链接(Apollo 的中间件等价物)来拦截从服务器返回的响应数据,但在它插入缓存和重新渲染组件之前。

这是一个示例,我们从 API 的扩展中提取指标数据:

import { ApolloClient, InMemoryCache, HttpLink, ApolloLink } from 'apollo-boost'

const link = new HttpLink({
  uri: 'https://serve.onegraph.com/dynamic?show_metrics=true&app_id=<app_id>',
})

const metricsWatchers = {}

let id = 0

export function addMetricsWatcher(f) {
  const watcherId = (id++).toString(36)
  metricsWatchers[watcherId] = f
  return () => {
    delete metricsWatchers[watcherId]
  }
}

function runWatchers(requestMetrics) {
  for (const watcherId of Object.keys(metricsWatchers)) {
    try {
      metricsWatchers[watcherId](requestMetrics)
    } catch (e) {
      console.error('error running metrics watcher', e)
    }
  }
}

// We intercept the response, extract our extensions, mutatively store them,
// then forward the response to the next link
const trackMetrics = new ApolloLink((operation, forward) => {
  return forward(operation).map(response => {
    runWatchers(
      response
        ? response.extensions
          ? response.extensions.metrics
          : null
        : null
    )
    return response
  })
})

function create(initialState) {
  return new ApolloClient({
    link: trackMetrics.concat(link),
    cache: new InMemoryCache().restore(initialState || {}),
  })
}

const apolloClient = create(initialState);

然后在我们的 React 组件中使用结果:

import { addMetricsWatcher } from '../integration/apolloClient'

const Page = () => {
  const [requestMetrics, updateRequestMetrics] = useState(null)

  useEffect(() => {
    return addMetricsWatcher(requestMetrics =>
      updateRequestMetrics(requestMetrics)
    )
  })

// Metrics from extensions are available now
return null;
}

然后使用一些可变状态来跟踪每个请求及其结果,并使用该状态来呈现应用程序内的指标。

根据您希望如何使用扩展数据,这可能适合您,也可能不适合您。该实现是不确定的,并且在呈现的数据和您从扩展中提取的数据之间可能存在一些轻微的竞争条件。

在我们的案例中,我们将性能指标数据存储在扩展中 - 非常有用,但也是辅助性的 - 所以我们认为这种权衡是可以接受的。

Apollo 客户端 repo 上还有一个未解决的问题,用于跟踪此功能请求

于 2019-09-12T22:46:08.307 回答
0

我对 ApolloClient 没有任何想法,但我尝试在shopify graphql app中运行您的查询。它返回带有扩展名的结果。请在下面找到屏幕截图。您也可以在ApolloClient github 中提出问题。

在此处输入图像描述

于 2019-09-11T14:12:15.583 回答