GraphQL 查询结果中未返回的扩展

Posted

技术标签:

【中文标题】GraphQL 查询结果中未返回的扩展【英文标题】:Extensions not returned in GraphQL query results 【发布时间】:2020-01-11 22:34:59 【问题描述】:

我正在创建一个这样的 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
                
            
        
    `)

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

知道为什么吗?

非常感谢您的帮助

【问题讨论】:

【参考方案1】:

在we wrote up 之前有一个 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 跟踪 this feature request 的未解决问题

【讨论】:

谢谢@sgrove。我不完全在那里,但你让我走上了正确的轨道。在你的 trackMetrics 方法中添加日志我可以看到很棒的扩展,但我不知道如何在我的 client.query 调用中添加它们?【参考方案2】:

我不知道 ApolloClient,但我尝试在 shopify graphql app 中运行您的查询。它返回带有扩展名的结果。请在下面找到屏幕截图。也可以在ApolloClientgithub提问。

【讨论】:

谢谢。是的,我也在应用程序中这样做了。你说得对,我会联系 ApolloClient 是的 RaphArbuz,如果您找到任何解决方案,请在评论中提及。谢谢

以上是关于GraphQL 查询结果中未返回的扩展的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 graphq-request 表示嵌套对象输入类型的数组

我们如何从 GraphQL 的 RequestContextHolder 获取 GraphQL 的 HttpServletRequest(DefaultGlobalContext)(使用 graphq

GraphQL,使用 GraphiQL 的查询语法不正确

在 GraphQL 对象查询中使用变量

动态 SQL 在 Access 直通查询中未返回结果

Graphql 查询结果返回 undefined