所有 apollo 查询错误都会引发网络 400 错误

Posted

技术标签:

【中文标题】所有 apollo 查询错误都会引发网络 400 错误【英文标题】:All apollo query errors throw a network 400 error 【发布时间】:2018-09-26 01:50:37 【问题描述】:

如何全局处理我的查询和变异错误?当我在突变或查询中使用格式错误的 graphql 查询时,我的 react-native 应用程序总是抛出以下错误。

未处理(在 react-apollo:Apollo(MyScreen) 中)错误:网络错误: 响应不成功:收到状态码 400

在 graphiql 端点上运行相同的查询,但会提供相关错误。虽然目标是全局处理错误,但本地查询错误也对我不起作用。打印它们不会显示任何内容。

//MyComponent.js
class MyComponent extends React.Component 
  render () 
    /*
    outputs
    
      error: undefined
      loading: true
      networkStatus: 1
    
    */
    console.log(this.props.data);
    //outputs undefined
    console.log('error', this.props.error);
    //outputs undefined
    console.log('errors', this.props.errors);

    return (
      <Container>
        this.props.myData
        <Button block onPress=this.props.onPress>
          <Text>Button</Text>
        </Button>
      </Container>
    )
  


const mapDispatchToProps = (dispatch, navigation: navigate) => (
  onPress: async rest => 
    //do stuff
  
);

export default connect(null, mapDispatchToProps)(MyDataService.getMyDataInjector(MyComponent));


//MyDataService.js
import  graphql  from 'react-apollo';
import getApolloClient from '../../../apolloClient';
import  dataFragment  from './dataFragments';
import gql from 'graphql-tag';

export default MyDataService = 

  getMyDataInjector: graphql(gql`
    query 
      myData 
        ...dataFragment
      
    
    $dataFragment
  `,
  
    props: ( data, errors, error ) => (
      data,
      loading: data.loading,
      myData: data.myData,
      errors,
      error,
    )
  ),

  addData: async (data) => 
    const res = await apolloClient.mutate(
      mutation: gql`
        mutation addData($data: String!) 
          addData(data: $data) 
            ...dataFragment
          
        
        $dataFragment
      `,
      variables: 
        data,
      
    );

    return res.data.addData;
  ,
;


//apolloClient.js
import  ApolloClient  from 'apollo-client';
import  HttpLink  from 'apollo-link-http';
import  setContext  from 'apollo-link-context';
import  onError  from 'apollo-link-error';
import  InMemoryCache, defaultDataIdFromObject   from 'apollo-cache-inmemory';

let apolloClient;

const initApolloClient = store => 
  const httpLink = new HttpLink(uri: 'http://192.168.0.11:3000/graphql')

  // const errorLink = onError(( response, graphQLErrors, networkError ) => 
  //   console.log('graphql error in link', graphQLErrors);
  //   console.log('networkError error in link', networkError);
  //   console.log('response error in link', response);

  //   if (graphQLErrors)
  //     graphQLErrors.map(( message, locations, path ) =>
  //       console.log(
  //         `[GraphQL error]: Message: $message, Location: $locations, Path: $path`,
  //       ),
  //     );
  //   if (networkError) console.log(`[Network error]: $networkError`);
  // );

  const authLink = setContext((_,  headers ) => 
    const accessToken: type, token = store.getState().signedInUser;
    return 
      headers: 
        ...headers,
        authorization: type && token ? type + ' ' + token : null 
      
    
  );

  apolloClient =  new ApolloClient(
    // using error link throws - Error: Network error: forward is not a function
    // link: authLink.concat(errorLink, httpLink),
    link: authLink.concat(httpLink),
    // doesn't console log
    // onError: (e) =>  console.log('IN ON ERROR', e.graphQLErrors) ,
    cache: new InMemoryCache(
      dataIdFromObject: o => (o._id ? `$o.__typename:$o._id`: null),
    ),
    // turning these on do nothing
    // defaultOptions: 
    //   query: 
    //     // fetchPolicy: 'network-only',
    //     errorPolicy: 'all',
    //   ,
    //   mutate: 
    //     errorPolicy: 'all'
    //   
    // 
  );

  return apolloClient;



export default getApolloClient = () => apolloClient;

export  initApolloClient ;

【问题讨论】:

【参考方案1】:

能够通过使用带有 onError 的 apollo-link 使其工作。

import  ApolloClient  from 'apollo-client';
import  ApolloLink  from 'apollo-link';
import  HttpLink  from 'apollo-link-http';
import  setContext  from 'apollo-link-context';
import  onError  from 'apollo-link-error';
import  InMemoryCache, defaultDataIdFromObject   from 'apollo-cache-inmemory';

let apolloClient;

const initApolloClient = store => 
  const httpLink = new HttpLink(uri: 'http://192.168.0.11:3000/graphql')

  const errorLink = onError(( graphQLErrors, networkError ) => 
    if (graphQLErrors) 
      graphQLErrors.map(( message, locations, path ) =>
        console.error(
          `[GraphQL error]: Message: $message, Location: $JSON.stringify(locations), Path: $path`,
        ),
      );
    

    if (networkError) console.error(`[Network error]: $networkError`);
  );

  const authLink = setContext((_,  headers ) => 
    const accessToken: type, token = store.getState().signedInUser;
    return 
      headers: 
        ...headers,
        authorization: type && token ? type + ' ' + token : null 
      
    
  );

  const link = ApolloLink.from([
    authLink,
    errorLink,
    httpLink,
  ]);

  apolloClient =  new ApolloClient(
    link,
    cache: new InMemoryCache(
      //why? see https://***.com/questions/48840223/apollo-duplicates-first-result-to-every-node-in-array-of-edges/49249163#49249163
      dataIdFromObject: o => (o._id ? `$o.__typename:$o._id`: null),
    ),
  );

  return apolloClient;

【讨论】:

以上是关于所有 apollo 查询错误都会引发网络 400 错误的主要内容,如果未能解决你的问题,请参考以下文章

传递状态时 Apollo Query 变量错误

Apollo + React 在执行突变时给了我 400 错误。可能的 httpLink 错误

Android 设备上的 Apollo 网络错误(React Native)

如何从 graphql apollo 客户端查询中获取/记录/捕获错误

Apollo 服务器使用部分数据引发多个错误

Apollo - Uncaught (in promise) 错误:网络错误:无法读取未定义的属性“种类”