Flutter错误处理插件gql_error_link的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter 错误处理插件 gql_error_link 的使用

使用

以下是一个使用 ErrorLink 来处理认证异常的示例。

注意:此示例效率非常低,因为它不仅在每次请求时更新令牌,而且仅在请求失败后才进行更新。一个更完整的认证链接示例可以在 这里 查看。

import "package:gql/language.dart";
import "package:gql_error_link/gql_error_link.dart";
import "package:gql_exec/gql_exec.dart";
import "package:gql_link/gql_link.dart";

// 假设我们有一个终止链
final terminatingLink = Link.function(
  (request, [forward]) async* {
    // 它期望 [AuthToken] 存在于上下文中。
    final token = request.context.entry<AuthToken>();

    // 如果令牌不存在,则抛出 [AuthException]。
    if (token == null) {
      throw AuthException();
    }

    // 否则,生成一些 [Response]。
    yield Response(
      data: {
        "magic": token.token,
      },
    );
  },
);

// 在这种情况下,[AuthToken] 是一个简单的包含 [String] 令牌的容器。
class AuthToken extends ContextEntry {
  final String token;

  const AuthToken({required this.token});

  [@override](/user/override)
  List<Object> get fieldsForEquality => [];
}

// 我们的终止链定义了自己的 [AuthException]
class AuthException extends ServerException {}

// 我们有一些获取新有效令牌的方法
Future<String> getNewToken() => Future.delayed(
      Duration(milliseconds: 10),
      () => "Valid token",
    );

// 我们将处理 [LinkException]s
Stream<Response> handleException(
  Request request,
  NextLink forward,
  LinkException exception,
) async* {
  // 如果异常是 [AuthException]
  if (exception is AuthException) {
    // 获取新令牌
    final token = await getNewToken();

    // 更新请求以包含新令牌
    final updatedRequest = request.withContextEntry(
      AuthToken(token: token),
    );

    // 尝试再次请求
    yield* forward(updatedRequest);

    return;
  }

  // 否则,重新抛出之前的异常
  throw exception;
}

void main() async {
  // 我们通过在终止链之前添加 [ErrorLink] 来使用它
  final link = Link.from([
    ErrorLink(onException: handleException),
    terminatingLink,
  ]);

  try {
    // 让我们获取第一个响应
    final response = await link
        .request(
          Request(
            operation: Operation(
              document: parseString("{}"),
            ),
          ),
        )
        .first;

    // 内部的第一个响应是一个异常,但 [ErrorLink] 捕获了它,并使用有效的令牌重试请求
    print(response.data);
  } catch (e) {
    // 这个方法甚至不会被调用
    print(e);
  }
}

更多关于Flutter错误处理插件gql_error_link的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter错误处理插件gql_error_link的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用gql_error_link进行GraphQL错误处理的示例代码。gql_error_linkgraphql_flutter包中的一个链接(Link),用于在GraphQL请求发生错误时进行处理。

首先,确保你的pubspec.yaml文件中已经包含了graphql_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  graphql_flutter: ^x.y.z  # 替换为最新版本号

然后,你可以按照以下步骤设置和使用gql_error_link

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:graphql/client.dart';
  1. 定义你的GraphQL客户端和错误处理逻辑
void main() {
  // 1. 创建HttpLink
  final HttpLink httpLink = HttpLink(
    'https://your-graphql-endpoint.com/graphql',
  );

  // 2. 创建ErrorLink
  final Link errorLink = gql_error_link.ErrorLink(
    onError: (GraphQLError error, Operation operation, GraphQLExecutor executor, GraphQLOptions options) {
      // 在这里处理错误,例如打印错误信息或显示Snackbar
      print('GraphQL Error: ${error.message}');

      // 如果需要,可以在这里决定是否重试请求
      // executor.resume(operation, options); // 这将重试请求
    },
  );

  // 3. 使用Link链
  final Link link = errorLink.concat(httpLink);

  // 4. 创建ValueNotifier以保存GraphQL客户端
  final ValueNotifier<GraphQLClient> client = ValueNotifier(
    GraphQLClient(
      cache: InMemoryCache(),
      link: link,
    ),
  );

  runApp(MyApp(client: client));
}

class MyApp extends StatelessWidget {
  final ValueNotifier<GraphQLClient> client;

  MyApp({required this.client});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('GraphQL Flutter App')),
        body: MyHomePage(client: client),
      ),
    );
  }
}
  1. 在你的页面中使用GraphQL客户端进行查询
class MyHomePage extends StatefulWidget {
  final ValueNotifier<GraphQLClient> client;

  MyHomePage({required this.client});

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late QueryResult result;

  @override
  void initState() {
    super.initState();

    // 执行GraphQL查询
    widget.client.value.query(
      QueryOptions(
        document: gql(r'''
          query {
            viewer {
              id
              name
            }
          }
        '''),
      ),
    ).listen(
      (QueryResult value) {
        setState(() {
          result = value;
          // 检查是否有错误
          if (result.hasErrors) {
            result.errors!.forEach((error) {
              print('Query Error: ${error.message}');
            });
          }
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    if (result.loading) {
      return Center(child: CircularProgressIndicator());
    }

    if (result.hasErrors) {
      return Center(child: Text('Error loading data'));
    }

    return ListView.builder(
      itemCount: result.data!['viewer']!['id']?.length ?? 0, // 假设你的数据结构中有id字段
      itemBuilder: (context, index) {
        // 根据你的数据结构显示数据
        return ListTile(
          title: Text('ID: ${result.data!['viewer']!['id']}'),
          subtitle: Text('Name: ${result.data!['viewer']!['name']}'),
        );
      },
    );
  }
}

在这个示例中,我们创建了一个HttpLink用于与GraphQL服务器通信,并创建了一个ErrorLink用于处理GraphQL请求中的错误。然后,我们将这两个链接组合起来,并创建了一个GraphQLClient。在错误处理逻辑中,我们简单地打印了错误信息,但你也可以根据需要添加更多的错误处理逻辑,比如显示UI错误提示或重试请求。

注意:实际使用中,请根据你的GraphQL查询和数据结构调整代码。

回到顶部