是否可以将重复的发送/响应封装到单个异步函数中的相同dart隔离中?
背景:
为了设计方便的API,我希望有一个函数以异步方式返回由隔离产生的结果,例如
var ans = await askIsolate(isolateArgs);
如果我直接使用spawnUri调用生成的响应,例如
Future<String> askIsolate(Map<String,dynamic> isolateArgs) {
ReceivePort response = new ReceivePort();
var uri = Uri.parse(ISOLATE_URI);
Future<Isolate> remote = Isolate.spawnUri(uri, [JSON.encode(isolateArgs)], response.sendPort);
return remote.then((i) => response.first)
.catchError((e) { print("Failed to spawn isolate"); })
.then((msg) => msg.toString());
}
但是,上述方法的缺点是,如果我需要重复调用askIsolate,则必须每次都产生隔离。
相反,我想与正在运行的隔离进行通信,这当然可以通过使隔离将sendPort返回给调用方来实现。但是我相信,自2013 Isolate refactoring以来,这要求调用者在receivePort上侦听后续消息,从而使封装在单个异步函数中成为不可能。
有什么机制可以实现我所缺少的吗?
最佳答案
答案取决于您打算如何使用隔离器
我猜是后者,并且您的
askIsolate()
函数需要立即返回一个Future
,它在收到所有答案时将不完整。await for
循环可用于侦听流并消耗事件,直到关闭为止。我对隔离株不熟悉,所以我希望这没问题,我没有测试过。我假设隔离终止并且响应关闭。
String askIsolate(Map<String,dynamic> isolateArgs) async {
ReceivePort response = new ReceivePort();
var uri = Uri.parse(ISOLATE_URI);
Isolate.spawnUri(uri, [JSON.encode(isolateArgs)], response.sendPort)
.catchError((e)) {
throw ...;
});
List<String> answers = new List<String>;
await for(var answer in response) {
out.add(answer.toString());
}
return answers;
}
注意:
response
是您正在听的答案流。它是在产生隔离对象之前创建的,因此您无需(而且可能不应)等待隔离对象的将来完成之前就可以收听。 askIsolate()
异步,因为这样可以很容易地立即返回一个将来在函数返回时完成的功能-无需对.then(...)
链进行所有繁琐的处理,我个人觉得这很令人困惑且难以阅读。 顺便说一句,您的原始
then(...).catchError(...)
样式代码最好这样写: Isolate.spawnUri(uri, [JSON.encode(isolateArgs)], response.sendPort)
.catchError((e) { ... });
return response.first)
.then((msg) => msg.toString());
我相信,在隔离的创建之后延迟将catchError处理程序附加到该行可能会使将来在处理程序到位之前完成一个错误。
请参阅:https://www.dartlang.org/articles/futures-and-error-handling/#potential-problem-failing-to-register-error-handlers-early。
关于dart - 将重复的发送/响应封装到单个异步函数中的同一Dart隔离中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36500139/