当服务器关闭时 React-Apollo 捕获

Posted

技术标签:

【中文标题】当服务器关闭时 React-Apollo 捕获【英文标题】:React-Apollo catch when server is down 【发布时间】:2020-09-14 23:01:48 【问题描述】:

在我的带有节点服务器的 React ApolloGraphQL 应用程序中,我试图让它在我的节点服务器关闭时捕获错误。当节点服务器启动时,一切正常且正常... graphQL 错误被捕获并显示。但是当我停止节点服务器时,我会遇到无法避免的运行时错误。当节点服务器关闭时,服务器会以 503 Service Unavailable 响应和非 JSON 的 html 页面进行响应。

apollo 客户端是这样设置的:

const client = new ApolloClient(
  assumeImmutableResults: true,
  fetchOptions: 
    credentials: "include"
  ,
  fetch: fetch,
  onError: ( graphQLErrors, networkError ) => 
    if (graphQLErrors)
      graphQLErrors.map(( message, locations, path ) =>
        console.log(`[GraphQL error]: Message: $message, Location: $locations, Path: $path`,),);
    if (networkError) console.log(`[Network error]: $networkError`);
    response = errors:null;
  ,
  cache: new InMemoryCache(
    freezeResults: true,
    dataIdFromObject: obj => 
      let dataId = null;
      switch (obj.__typename) 
        default:
          dataId = defaultDataIdFromObject(obj);
      
      return dataId;
    ,
    cacheRedirects: 
      Query: 
        productVariant: (_, args,  getCacheKey ) => 
          const cacheKey = getCacheKey( __typename: "ProductVariant", ...args );
          return cacheKey;
        
      
    ,
  ),
);

上面的onError 阻止响应此消息:

Error: Network error: JSON.parse: unexpected character at line 1 column 1 of the JSON data

我以这种方式设置了突变:

const [mutateVariant, data, error, loading] = useMutation(UPDATE_PRODUCT_META);

我这样称呼它:

mutateVariant( variables: inputM: ...buildMetaInput(editedData) , 
    errorPolicy: 'ignore', onError: (error) => Logger("Error:", error));

您可以看到我已经尝试了不同的errorPolicy 设置并添加了onError 回调。

但我不断收到未处理的运行时错误,似乎无法捕捉和处理它们:

Unhandled Runtime Error

Error: Network error: JSON.parse: unexpected character at line 1 column 1 of the JSON data
Call Stack
ApolloError           webpack-internal:///./node_modules/apollo-client/bundle.esm.js (76:28)
error                 webpack-internal:///./node_modules/apollo-client/bundle.esm.js (1041:48)
notifySubscription    webpack-internal:///./node_modules/zen-observable/lib/Observable.js (140:18)
onNotify              webpack-internal:///./node_modules/zen-observable/lib/Observable.js (179:21)
error                 webpack-internal:///./node_modules/zen-observable/lib/Observable.js (240:15)
error/<               webpack-internal:///./node_modules/apollo-client/bundle.esm.js (880:76)
error                 webpack-internal:///./node_modules/apollo-client/bundle.esm.js (880:27)
notifySubscription    webpack-internal:///./node_modules/zen-observable/lib/Observable.js (140:18)
onNotify              webpack-internal:///./node_modules/zen-observable/lib/Observable.js (179:21)
error                 webpack-internal:///./node_modules/zen-observable/lib/Observable.js (240:15)
error                 webpack-internal:///./node_modules/apollo-link-error/lib/bundle.esm.js (53:34)
notifySubscription    webpack-internal:///./node_modules/zen-observable/lib/Observable.js (140:18)
onNotify              webpack-internal:///./node_modules/zen-observable/lib/Observable.js (179:21)
error                 webpack-internal:///./node_modules/zen-observable/lib/Observable.js (240:15)
createHttpLink/</</<  webpack-internal:///./node_modules/apollo-link-http/lib/bundle.esm.js (92:26)

useMutation 钩子返回的error 数据:

graphQLErrors: Array []
message: "Network error: JSON.parse: unexpected character at line 1 column 1 of the JSON data"
​networkError: …
​  ​bodyText: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>503 Service 
  Unavailable</title>\n</head><body>\n<h1>Service Unavailable</h1>\n<p>The server is temporarily unable 
  to service your\nrequest due to maintenance downtime or capacity\nproblems. Please try again later.  
  </p>\n<p>Additionally, a 503 Service Unavailable\nerror was encountered while trying to use an 
  ErrorDocument to handle the request.</p>\n</body></html>\n"
  name: "ServerParseError"
​​  response: Object   
​​  statusCode: 503

如何发现这个错误?

【问题讨论】:

我不确定这是否有意义(完全),但如果你没有找到更好的解决方案,你可以包装你传递给新的 ApolloClient 的 fetch 函数(例如const newFetch = (url, options) =&gt; /* ... */) .在您的包装器中,您可以检查您的错误并在这种情况下返回模拟的模拟响应????‍♀️。我会寻找比这更聪明的解决方案,尽管哈哈 【参考方案1】:

mutateVariant 函数返回一个承诺。尝试在调用后添加一个 .catch()。

mutateVariant().catch(() => ...);

【讨论】:

以上是关于当服务器关闭时 React-Apollo 捕获的主要内容,如果未能解决你的问题,请参考以下文章

未捕获的错误:react-apollo 仅支持每个 HOC 的查询、订阅或突变

在 react-apollo 的 Query 组件中设置状态

react-apollo 没有连接到我的 graphql 本地服务器

react-apollo 网络错误:查询“Hello”的服务器响应丢失

react-apollo 服务器端渲染

当 catch 语句没有显式捕获异常对象时,它们是不是更快/更便宜? [关闭]