Reputation: 2417
Basically I am now very confused: the setup is very simple - I want to use dart to write the main app and the web worker part - a part that requires access to the same APIs the regular JS web worker has and that runs as a real worker when deployed (i.e. compiled to js).
As far as I understand dart isolates are not what I want because when compiled to JS those execute as part of the main thread even if they do not share state with the main code - this is not acceptable for my use case.
Also if I understand correctly I cannot use dart code if I am to use Worker API with a script uri, but even if I could it has to be a completely separate project and cannot be part of my main code (like it is with isolates).
Is my scenario possible at all with the current state of Dart? A simplified example on how to use web worker from dart and write the worker code in dart as well and having access to xmlhttprequest would be great. I am aware that I would probably not be able to transfer objects without serialization/deserialization but that is okay.
Thanks.
Upvotes: 3
Views: 1840
Reputation: 11
I managed to get exactly this work but with a caveat.
Here's how the main.dart looks like
import 'dart:async';
import 'dart:html';
import 'package:excel_worker/dog.dart';
void main() {
var w = Worker('worker/dog_raiser.dart.js');
// Listen to Worker's postMessage().
// dart.html convert the callback to a Stream.
w.onMessage.listen((msg) {
var dog = Dog(name: msg.data['name'], age: msg.data['age']);
print('master took back ${dog.name} and she turns into ${dog.age}!');
});
// After one second, post a message to the Worker.
new Timer(Duration(seconds:1), () {
w.postMessage(Dog(name : 'Marley', age: 1));
});
}
Here's the worker.
import 'package:js/js.dart';
import 'package:excel_worker/dog.dart';
@anonymous
@JS()
abstract class MessageEvent {
external dynamic get data;
}
@JS('postMessage')
external void PostMessage(obj);
@JS('onmessage')
external void set onMessage(f);
void main() {
print('Worker created');
// 'allowInterop' is necessary to pass a function into js.
onMessage = allowInterop((event) {
var e = event as MessageEvent;
var dog = e.data as Dog;
print('worker: got ${dog.name} from master, raising it from ${dog.age}...');
PostMessage(Dog(name : '${dog.name} 2.0', age: dog.age + 1));
});
}
main.dart
and worker.dart
both need to reside in the web/
folder. They share the same custom package of dog, which lived in the lib/
folder.
Now, the major caveat: to run this web app with web worker correctly in the browser during development, instead of the common webdev serve
, we need to use webdev serve -r
. Which indicate a release version, in other word, use dart2js instead of dartdevc.
Here's the git repro if you like to check out the whole working example: https://github.com/yuan-kuan/dog-raiser
Upvotes: 0
Reputation: 2971
Isolates in dart2js will be mapped to workers. And you should be able to use either spawn or spawnUri. So that part should be fine.
At the moment you're more likely to have problems developing in Dartium, where isolates don't map to workers. They run in parallel, but don't have access to worker APIs. That's being worked on. That's also the reason you can't use spawn in Dartium, to prevent spawning something with dart:html code that will break if it tries to use those APIs. It's unfortunate that even something as simple as print() will throw in a Dartium isolate right now. But as far as I know, it all works well in deployment.
Upvotes: 3