ferry icon indicating copy to clipboard operation
ferry copied to clipboard

[Proposal] Allow user to cancel request.

Open T-moz opened this issue 2 years ago • 1 comments

I didn't find a way to cancel request that are not needed anymore, even by using DioLink.

The problem is that http request are still going in the background event if Widgets or providers are disposed.

It could look like something like that:

import 'package:flutter/material.dart';
import 'package:ferry/ferry.dart';
import 'package:get_it/get_it.dart';
import 'package:ferry_flutter/ferry_flutter.dart';
import 'package:built_collection/built_collection.dart';

import './graphql/__generated__/all_pokemon.data.gql.dart';
import './graphql/__generated__/all_pokemon.req.gql.dart';
import './graphql/__generated__/all_pokemon.var.gql.dart';
import './pokemon_card.dart';

class PokemonListScreen extends StatefulWidget {
  @override
  State<PokemonListScreen> createState() => _PokemonListScreenState();
}

class _PokemonListScreenState extends State<PokemonListScreen> {
  final client = GetIt.I<Client>();
  final cancelToken = CancelToken();

  @override
  void dispose() {
    cancelToken.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('All Pokemon'),
      ),
      body: Operation<GAllPokemonData, GAllPokemonVars>(
        client: client,
        cancelToken: cancelToken,
        operationRequest: GAllPokemonReq(
          (b) => b
            ..vars.limit = 50
            ..vars.offset = 0,
        ),
        builder: (context, response, error) {
          if (response!.loading)
            return Center(child: CircularProgressIndicator());

          final pokemons = response.data?.pokemons?.results ?? BuiltList();

          return ListView.builder(
            itemCount: pokemons.length,
            itemBuilder: (context, index) => PokemonCard(
              pokemon: pokemons[index],
            ),
          );
        },
      ),
    );
  }
}

or without ferry flutter (riverpod in this case):

final allPokemonProvider =
    StreamProvider.autoDispose<GAllPokemonData_pokemons_results?>((ref) {
  final client = ref.watch(graphqlClientProvider);
  final cancelToken = CancelToken();

  ref.onDispose(() {
    cancelToken.cancel();
  });

  return client
      .request(GAllPokemonReq(), cancelToken: cancelToken)
      .map((event) => event.data?.pokemons?.results);
});

T-moz avatar Mar 26 '22 17:03 T-moz

Same issue any update for this stuff? How is possible to cancel the previous request before I create a new one to reduce the workload to the backend side?

EhabSalah avatar May 13 '22 15:05 EhabSalah