channel method
Converts this port to a two-way communication channel, exposed as a
StreamChannel
.
This can be used to implement a remote database connection over service workers.
The explicitClose
parameter can be used to control whether a close
message should be sent through the channel when it is closed. This will
cause it to be closed on the other end as well. Note that this is not a
reliable way of determining channel closures though, as there is no event
for channels being closed due to a tab or worker being closed.
Both "ends" of a JS channel calling channel on their part must use the
value for explicitClose
.
When webNativeSerialization
is enabled, the StreamChannel
can only be
used for drift databases using the package:drift/remote.dart
protocol
and is not suitable for any other message.
This allows disabling the serialize
parameter on connectToRemoteAndInitialize
and improves performance. Both endpoints need to use the same values for
explicitClose
and webNativeSerialization
.
Implementation
StreamChannel<Object?> channel({
bool explicitClose = false,
bool webNativeSerialization = false,
}) {
final controller = StreamChannelController<Object?>();
onmessage = (web.MessageEvent event) {
final message = event.data;
if (explicitClose && message == _disconnectMessage.toJS) {
// Other end has closed the connection
controller.local.sink.close();
} else if (webNativeSerialization) {
controller.local.sink.add(_protocol.deserialize(message as JSArray));
} else {
controller.local.sink.add(message.dartify());
}
}.toJS;
controller.local.stream.listen((e) {
if (webNativeSerialization) {
final serialized = _protocol.serialize(e as Message);
postMessage(serialized);
} else {
postMessage(e.jsify());
}
}, onDone: () {
// Closed locally, inform the other end.
if (explicitClose) {
postMessage(_disconnectMessage.toJS);
}
close();
});
return controller.foreign;
}