我有一个网址列表,我必须按顺序检查。当在网址上检索到的内容之一与给定条件匹配时,我必须停止,否则必须测试下一个网址。
问题是检索给定网址的内容是一个异步任务,所以我不能使用简单的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();
答案 0 :(得分:1)
Quiver package包含几个用异步迭代的函数。
doWhileAsync
,reduceAsync
和forEachAsync
对Iterables上的元素执行异步计算,等待计算在处理下一个元素之前完成。
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);
}
}));
答案 1 :(得分:0)
我所拥有的一个想法是将整个操作的结果分成另一个Future
,其中有反应。此未来传输已找到且有效的URL的内容或可对其作出反应的错误。异步getContent
操作的完成要么在结果,错误或再次尝试中完成未来。
请注意,在此(和您的)方法中,在运行操作时,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
});