如果请求多次,如何忽略之前请求的API

问题描述 投票:0回答:5

我在我的 flutter 应用程序中使用 HTTP 请求来处理 API。我实现了用于搜索产品的 API,一旦收到响应,它将显示在我的 UI 上。我的问题是请求的 API 将在不同的时间返回,这意味着如果我搜索“sweets”,如果输入“s”,它将启动一个搜索“s”的 API 请求,输入“so”后,它将发送另一个API调用,但是“SW”响应可能首先来自服务器,然后才到达“s”结果。它将替换我需要在应用程序中显示的确切结果。如何预防这个问题?

flutter api rest dart httprequest
5个回答
2
投票

有一个概念叫做

debounce
。它只是意味着它可以等待特定时间来触发回调。

Dart 中还有一个 Callable Classes 的概念,你可以使用它们来进行反跳:

import 'dart:async';

class Debounce {
  Duration delay;
  Timer? _timer;

  Debounce(
    this.delay,
  );

  call(void Function() callback) {
    _timer?.cancel();
    _timer = Timer(delay, callback);
  }

  dispose() {
    _timer?.cancel();
  }
}

使用简单

// 1 - Create a debounce instance
final Debounce _debounce = Debounce(Duration(milliseconds: 400));

// 2 - Use it
_debounce((){ print('First'); });
_debounce((){ print('Second'); });
_debounce((){ print('Third'); });

// ...after 400ms you'll see "Third"

对于您的具体示例,处置计时器非常重要,以防它在处置后使用您的 TextController:

final TextEditingController _controller = TextEditingController();
final Debounce _debounce = Debounce(Duration(milliseconds: 400));

@override
void dispose() {
  _controller.dispose();
  _debounce.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return TextField(
    controller: _controller,
    onChanged: (String value) {
      _debounce((){
        print('Value is $value');
      });
    },
  );
}

来源


0
投票

您可以通过输入过滤您的响应来处理它。例如,如果传入响应是“sw”并且用户已经仅键入了“sw”,则用布尔值将其标记为“true”并忽略进一步的响应,或者如果传入响应是“s”但用户已输入“sw”,将其布尔值标记为“false”并忽略它,不要让它替换您以前的数据。

您可以顺便在对象模型中定义这个布尔值。


0
投票

我的理解是,您有一个文本字段,并且您正在尝试调用 onChanged 函数内的 API,并且您希望在输入新字符之前给用户一些时间来查看结果。 您有两个选择:

  1. 使用计时器在每次通话时将通话延迟几秒钟。
  2. 使用TextEditingController而不是依赖onChanged。然后在 onSubmited 函数中调用 API。

0
投票

您可以为您进行的每个 API 调用使用唯一的标志。这些标志可以在本地缓存,并在进行另一个 API 调用之前检查标志是否存在。


0
投票

这里有一个示例,如果您使用

AutoComplete
Widget

class DebounceSearch {
  final Duration duration;
  Timer? _timer;

  DebounceSearch({required this.duration});

  Future<List<String>> run(FutureOr<List<String>> Function() action) async {
    if (null != _timer) _timer?.cancel();

    Completer<List<String>> completer = Completer();
    _timer = Timer(duration, () async {
      var result = await action();
      completer.complete(result);
    });
    return completer.future;
  }
}

在您的页面上:

final debouncer = DebounceSearch(duration: 300.milliseconds);

Autocomplete(
   /// ...
   optionsBuilder: (s) async {
      return await debouncer.run(() async {
         return await _repo.findAutoComplete(s.text);
      });
   },
   /// ...
),

回购/提供者:

Future<List<String>> findAutoComplete(String s) async {
   /// call your api here
}

抱歉我的英语不好,但希望能帮助你解决问题

© www.soinside.com 2019 - 2024. All rights reserved.