2015-07-10 16:09:18 -07:00
|
|
|
/// <reference path="../../../globals.d.ts" />
|
|
|
|
|
import {MessageBus} from "angular2/src/web-workers/shared/message_bus";
|
|
|
|
|
import {print, isPresent, DateWrapper, stringify} from "../../facade/lang";
|
|
|
|
|
import {Promise, PromiseCompleter, PromiseWrapper} from "angular2/src/facade/async";
|
|
|
|
|
import {ListWrapper, StringMapWrapper, MapWrapper} from "../../facade/collection";
|
|
|
|
|
import {Serializer} from "angular2/src/web-workers/shared/serializer";
|
2015-07-10 16:09:18 -07:00
|
|
|
import {Injectable} from "angular2/di";
|
|
|
|
|
import {Type} from "angular2/src/facade/lang";
|
2015-07-10 16:09:18 -07:00
|
|
|
|
2015-07-10 16:09:18 -07:00
|
|
|
@Injectable()
|
2015-07-10 16:09:18 -07:00
|
|
|
export class MessageBroker {
|
|
|
|
|
private _pending: Map<string, Function> = new Map<string, Function>();
|
|
|
|
|
|
2015-07-10 16:09:18 -07:00
|
|
|
constructor(private _messageBus: MessageBus, protected _serializer: Serializer) {
|
|
|
|
|
this._messageBus.source.addListener((data) => this._handleMessage(data['data']));
|
2015-07-10 16:09:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _generateMessageId(name: string): string {
|
|
|
|
|
var time: string = stringify(DateWrapper.toMillis(DateWrapper.now()));
|
|
|
|
|
var iteration: number = 0;
|
|
|
|
|
var id: string = name + time + stringify(iteration);
|
|
|
|
|
while (isPresent(this._pending[id])) {
|
|
|
|
|
id = `${name}${time}${iteration}`;
|
|
|
|
|
iteration++;
|
|
|
|
|
}
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-10 16:09:18 -07:00
|
|
|
runOnUiThread(args: UiArguments, returnType: Type): Promise<any> {
|
2015-07-10 16:09:18 -07:00
|
|
|
var fnArgs = [];
|
|
|
|
|
if (isPresent(args.args)) {
|
|
|
|
|
ListWrapper.forEach(args.args, (argument) => {
|
2015-07-10 16:09:18 -07:00
|
|
|
if (argument.type != null) {
|
|
|
|
|
fnArgs.push(this._serializer.serialize(argument.value, argument.type));
|
|
|
|
|
} else {
|
|
|
|
|
fnArgs.push(argument.value);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var promise: Promise<any>;
|
|
|
|
|
var id: string = null;
|
|
|
|
|
if (returnType != null) {
|
2015-07-24 17:24:28 -07:00
|
|
|
var completer: PromiseCompleter<any> = PromiseWrapper.completer();
|
2015-07-10 16:09:18 -07:00
|
|
|
id = this._generateMessageId(args.type + args.method);
|
|
|
|
|
this._pending.set(id, completer.resolve);
|
|
|
|
|
PromiseWrapper.catchError(completer.promise, (err, stack?) => {
|
|
|
|
|
print(err);
|
|
|
|
|
completer.reject(err, stack);
|
2015-07-10 16:09:18 -07:00
|
|
|
});
|
2015-07-10 16:09:18 -07:00
|
|
|
|
|
|
|
|
promise = PromiseWrapper.then(completer.promise, (data: MessageResult) => {
|
|
|
|
|
if (this._serializer == null) {
|
|
|
|
|
return data.value;
|
|
|
|
|
} else {
|
|
|
|
|
return this._serializer.deserialize(data.value, returnType);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
promise = null;
|
2015-07-10 16:09:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(jteplitz602): Create a class for these messages so we don't keep using StringMap
|
2015-07-10 16:09:18 -07:00
|
|
|
var message = {'type': args.type, 'method': args.method, 'args': fnArgs};
|
|
|
|
|
if (id != null) {
|
|
|
|
|
message['id'] = id;
|
|
|
|
|
}
|
2015-07-10 16:09:18 -07:00
|
|
|
this._messageBus.sink.send(message);
|
2015-07-10 16:09:18 -07:00
|
|
|
|
|
|
|
|
return promise;
|
2015-07-10 16:09:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _handleMessage(message: StringMap<string, any>): void {
|
|
|
|
|
var data = new MessageData(message);
|
|
|
|
|
// TODO(jteplitz602): replace these strings with messaging constants
|
|
|
|
|
var id = data.value.id;
|
|
|
|
|
if (this._pending.has(id)) {
|
|
|
|
|
this._pending.get(id)(data.value);
|
|
|
|
|
this._pending.delete(id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MessageData {
|
|
|
|
|
type: string;
|
|
|
|
|
value: MessageResult;
|
|
|
|
|
|
|
|
|
|
constructor(data: StringMap<string, any>) {
|
|
|
|
|
this.type = StringMapWrapper.get(data, "type");
|
|
|
|
|
if (StringMapWrapper.contains(data, "value")) {
|
|
|
|
|
this.value = new MessageResult(StringMapWrapper.get(data, "value"));
|
|
|
|
|
} else {
|
|
|
|
|
this.value = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MessageResult {
|
|
|
|
|
id: string;
|
|
|
|
|
value: any;
|
|
|
|
|
|
|
|
|
|
constructor(result: StringMap<string, any>) {
|
|
|
|
|
this.id = StringMapWrapper.get(result, "id");
|
|
|
|
|
this.value = StringMapWrapper.get(result, "value");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class FnArg {
|
|
|
|
|
constructor(public value, public type) {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class UiArguments {
|
|
|
|
|
constructor(public type: string, public method: string, public args?: List<FnArg>) {}
|
|
|
|
|
}
|