如何链接异步任务?

3

我有一个要逐个检查的url列表。当从url检索到的内容与给定的条件匹配时,我必须停止,否则必须测试下一个url。

问题是为了检索给定的url的内容是一个异步任务,所以我不能使用简单的for-each循环。

最佳方法是什么?

目前我的代码看起来像这样:

List<String> urls = [/*...*/];
void f() {
  if (urls.isEmpty) return; // no more url available
  final url = urls.removeAt(0);
  getContent(url).then((content) {
    if (!matchCriteria(content)) f(); // try with next url
    else doSomethingIfMatch();
  });
}
f();
2个回答

1

Quiver package 包含了几个与异步迭代有关的函数。

doWhileAsyncreduceAsyncforEachAsync 在可迭代对象的元素上执行异步计算,在处理下一个元素之前等待计算完成。

doWhileAsync 看起来正是所需的:

List<String> urls = [/*...*/];
doWhileAsync(urls, (url) => getContent(url).then((content) {
  if (!matchCriteria(content)) {
    return new Future.value(true); // try with next url
  } else {
    doSomethingIfMatch();
    return new Future.value(false);
  }
}));

0

我有一个想法,就是将整个操作的结果分离到另一个Future中,然后对其进行反应。这个future会传输找到并且有效的URL的内容或者可以被反应的错误。异步getContent操作的完成要么用结果、错误来实现future的完成,要么重试。

请注意,在这种(和您的)方法中,当操作正在运行时,urls列表不得被任何其他方法修改。如果列表在每个序列开始时都是新创建的(就像示例一样),那么一切都很好。

List<String> urls = [/*...*/];
Completer<String> completer = new Completer<String>();

void f() {
  if (urls.isEmpty) completer.completeError(new Exception("not found"));
  final url = urls.removeAt(0);
  getContent(url).then((content) {
    if (!matchCriteria(content)) f(); // try with next url
    else completer.complete(content);
  }).catchError((error) { completer.completeError(error); });
}

completer.future.then((content) {
  // url was found and content retrieved      
}).catchError((error) {
  // an error occured or no url satisfied the criteria
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接