fix(WebWorkers): Run XHR requests on the UI

Fixes issues in dart where dart:html is not available in isolates and
allows for better profiling of XHR requests

Closes #3652
This commit is contained in:
Jason Teplitz 2015-08-14 15:09:58 -07:00
parent ee5df00146
commit 296851797b
5 changed files with 90 additions and 4 deletions

View File

@ -31,6 +31,7 @@ import {WebWorkerElementRef} from 'angular2/src/web-workers/shared/api';
import {AnchorBasedAppRootUrl} from 'angular2/src/services/anchor_based_app_root_url';
import {Injectable} from 'angular2/di';
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
import {XHR} from 'angular2/src/render/xhr';
import {
serializeMouseEvent,
serializeKeyboardEvent,
@ -61,7 +62,7 @@ export class WebWorkerMain {
constructor(private _renderCompiler: RenderCompiler, private _renderer: Renderer,
private _renderViewWithFragmentsStore: RenderViewWithFragmentsStore,
private _serializer: Serializer, rootUrl: AnchorBasedAppRootUrl) {
private _serializer: Serializer, rootUrl: AnchorBasedAppRootUrl, private _xhr: XHR) {
this._rootUrl = rootUrl.value;
}
@ -207,9 +208,23 @@ export class WebWorkerMain {
}
}
private _handleXhrMessage(data: ReceivedMessage) {
var args = data.args;
switch (data.method) {
case "get":
var url = args[0];
var promise = this._xhr.get(url);
this._wrapWebWorkerPromise(data.id, promise, String);
break;
default:
throw new BaseException(data.method + " Not Implemented");
}
}
// TODO(jteplitz602): Create message type enum #3044
private _handleWebWorkerMessage(message: StringMap<string, any>) {
var data: ReceivedMessage = new ReceivedMessage(message['data']);
// TODO(jteplitz602): Replace these with MessageBUs channels #3661
switch (data.type) {
case "ready":
return this._sendInitMessage();
@ -217,6 +232,8 @@ export class WebWorkerMain {
return this._handleCompilerMessage(data);
case "renderer":
return this._handleRendererMessage(data);
case "xhr":
return this._handleXhrMessage(data);
}
}

View File

@ -34,7 +34,7 @@ import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/facade/asy
import {NgZone} from 'angular2/src/core/zone/ng_zone';
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
import {XHR} from 'angular2/src/render/xhr';
import {XHRImpl} from 'angular2/src/render/xhr_impl';
import {WebWorkerXHRImpl} from 'angular2/src/web-workers/worker/xhr_impl';
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
import {UrlResolver} from 'angular2/src/services/url_resolver';
import {AppRootUrl} from 'angular2/src/services/app_root_url';
@ -129,7 +129,8 @@ function _injectorBindings(appComponentType, bus: WebWorkerMessageBus,
Parser,
Lexer,
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(new PrintLogger()), []),
bind(XHR).toValue(new XHRImpl()),
WebWorkerXHRImpl,
bind(XHR).toAlias(WebWorkerXHRImpl),
ComponentUrlMapper,
UrlResolver,
StyleUrlResolver,

View File

@ -0,0 +1,19 @@
import {Injectable} from 'angular2/di';
import {Promise} from 'angular2/src/facade/async';
import {XHR} from 'angular2/src/render/xhr';
import {FnArg, UiArguments, MessageBroker} from 'angular2/src/web-workers/worker/broker';
/**
* Implementation of render/xhr that relays XHR requests to the UI side where they are sent
* and the result is proxied back to the worker
*/
@Injectable()
export class WebWorkerXHRImpl extends XHR {
constructor(private _messageBroker: MessageBroker) { super(); }
get(url: string): Promise<string> {
var fnArgs: List<FnArg> = [new FnArg(url, null)];
var args: UiArguments = new UiArguments("xhr", "get", fnArgs);
return this._messageBroker.runOnUiThread(args, String);
}
}

View File

@ -55,7 +55,7 @@ export function main() {
// set up the ui side
var webWorkerMain = new WebWorkerMain(tb.compiler, tb.renderer, uiRenderViewStore, uiSerializer,
new AnchorBasedAppRootUrl());
new AnchorBasedAppRootUrl(), null);
webWorkerMain.attachToWebWorker(uiMessageBus);
return broker;
}

View File

@ -0,0 +1,49 @@
import {
AsyncTestCompleter,
inject,
describe,
it,
expect,
beforeEach,
createTestInjector,
beforeEachBindings,
SpyObject,
proxy
} from 'angular2/test_lib';
import {IMPLEMENTS, Type} from 'angular2/src/facade/lang';
import {MessageBroker, UiArguments} from 'angular2/src/web-workers/worker/broker';
import {WebWorkerXHRImpl} from "angular2/src/web-workers/worker/xhr_impl";
import {PromiseWrapper} from "angular2/src/facade/async";
export function main() {
describe("WebWorkerXHRImpl", () => {
it("should pass requests through the broker and return the response",
inject([AsyncTestCompleter], (async) => {
const URL = "http://www.example.com/test";
const RESPONSE = "Example response text";
var messageBroker: any = new SpyMessageBroker();
messageBroker.spy("runOnUiThread")
.andCallFake((args: UiArguments, returnType: Type) => {
expect(args.type).toEqual("xhr");
expect(args.method).toEqual("get");
expect(args.args.length).toEqual(1);
expect(args.args[0].value).toEqual(URL);
return PromiseWrapper.wrap(() => { return RESPONSE; });
});
var xhrImpl = new WebWorkerXHRImpl(messageBroker);
xhrImpl.get(URL).then((response) => {
expect(response).toEqual(RESPONSE);
async.done();
});
}));
});
}
@proxy
@IMPLEMENTS(MessageBroker)
class SpyMessageBroker extends SpyObject {
constructor() { super(MessageBroker); }
noSuchMethod(m) { return super.noSuchMethod(m); }
}