Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

feat(http): Digest scope after HTTP responses. #68

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions lib/block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,17 @@ class _ComponentFactory {
cssFuture = new async.Future.value(null);
}
var blockFuture;
// Since we create a new Future, we need to manage the scope $apply
// explicitly instead of letting HTTP handle it.
// TODO(deboer): Move this $apply into a higher level of the framework
// (e.g. the compiler)
var onFutureDone = () {};
if (directive.$template != null) {
blockFuture =
new async.Future.value($blockCache.fromHtml(directive.$template));
onFutureDone = () {
shadowInjector.get(Scope).$apply();
};
} else if (directive.$templateUrl != null) {
blockFuture = $blockCache.fromUrl(directive.$templateUrl);
}
Expand All @@ -308,8 +316,10 @@ class _ComponentFactory {
shadowDom.innerHtml = '<style>$css</style>';
}
if (blockFuture != null) {
return blockFuture.then((BlockFactory blockFactory) =>
attachBlockToShadowDom(blockFactory));
return blockFuture.then((BlockFactory blockFactory) {
attachBlockToShadowDom(blockFactory);
onFutureDone();
});
}
return shadowDom;
}));
Expand All @@ -324,7 +334,6 @@ class _ComponentFactory {
attachBlockToShadowDom(BlockFactory blockFactory) {
var block = blockFactory(shadowInjector);
shadowDom.nodes.addAll(block.elements);
shadowInjector.get(Scope).$digest();
return shadowDom;
}

Expand Down
3 changes: 0 additions & 3 deletions lib/directives/ng_include.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ class NgIncludeAttrDirective {
// an url template
blockCache.fromUrl(value).then((createBlock) {
updateContent(createBlock);

// Http should take care of this
scope.$digest();
});
}
});
Expand Down
41 changes: 39 additions & 2 deletions lib/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ class Http {
Map<String, async.Future<String>> _pendingRequests = <String, async.Future<String>>{};
UrlRewriter rewriter;
HttpBackend backend;
Scope scope;

Http(UrlRewriter this.rewriter, HttpBackend this.backend);
Http(Scope this.scope, UrlRewriter this.rewriter, HttpBackend this.backend);

async.Future<String> getString(String url,
{bool withCredentials, void onProgress(ProgressEvent e), Cache cache}) {
Expand All @@ -55,9 +56,45 @@ class Http {
if (cache != null && _pendingRequests.containsKey(url)) {
return _pendingRequests[url];
}

var requestFuture;
async.runZonedExperimental(() {
requestFuture = _requestUnguarded(url,
method: method,
withCredentials: withCredentials,
responseType: responseType,
mimeType: mimeType,
requestHeaders: requestHeaders,
sendData: sendData,
onProgress: onProgress,
cache: cache).then((x) {
// Disallow $digest inside of http handlers.
scope.$beginPhase('http');
return x;
});
}, onDone: () {
scope.$clearPhase();
try {
scope.$apply();
} catch (e, s) {
dump('Exception from HTTP, Dart may throw a cryptic error next: $e\n\n$s');
rethrow;
}
});
return requestFuture;
}

async.Future<HttpResponse> _requestUnguarded(String url,
{String method, bool withCredentials, String responseType,
String mimeType, Map<String, String> requestHeaders, sendData,
void onProgress(dom.ProgressEvent e),
Cache<HttpResponse> cache}) {

var cachedValue = cache != null ? cache.get(url) : null;
if (cachedValue != null) {
return new async.Future.value(cachedValue);
// The then here forced runZoned's onDone handler to wait for the
// future to complete.
return new async.Future.value(cachedValue).then((x) => x);
}
var result = backend.request(url,
method: method,
Expand Down
14 changes: 7 additions & 7 deletions lib/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class Scope implements Map {
Watch watch;
Scope next, current, target = this;

_beginPhase('\$digest');
$beginPhase('\$digest');
try {
do { // "while dirty" loop
dirty = false;
Expand Down Expand Up @@ -255,7 +255,7 @@ class Scope implements Map {
}
} while (dirty || asyncQueue.length > 0);
} finally {
_clearPhase();
$clearPhase();
}
}

Expand Down Expand Up @@ -284,12 +284,12 @@ class Scope implements Map {

$apply([expr]) {
try {
_beginPhase('\$apply');
$beginPhase('\$apply');
return $eval(expr);
} catch (e, s) {
_exceptionHandler(e, s);
} finally {
_clearPhase();
$clearPhase();
try {
$root.$digest();
} catch (e, s) {
Expand Down Expand Up @@ -393,15 +393,15 @@ class Scope implements Map {
return event;
}

_beginPhase(phase) {
$beginPhase(phase) {
if ($root._phase != null) {
throw '${$root._phase} already in progress';
throw '${$root._phase} already in progress trying to start $phase.';
}

$root._phase = phase;
}

_clearPhase() {
$clearPhase() {
$root._phase = null;
}

Expand Down
7 changes: 4 additions & 3 deletions test/_http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ class MockHttp extends Http {
Map<String, MockHttpData> gets = {};
List futures = [];

MockHttp(UrlRewriter rewriter, HttpBackend backend) : super(rewriter, backend);
MockHttp(Scope scope, UrlRewriter rewriter, HttpBackend backend) : super(scope, rewriter, backend);

expectGET(String url, String content, {int times: 1}) {
gets[url] = new MockHttpData(content, times);
}

flush() => Future.wait(futures);

assertAllGetsCalled() {
if (gets.length != 0) {
throw "Expected GETs not called $gets";
Expand Down Expand Up @@ -56,8 +56,9 @@ class MockHttpBackend extends HttpBackend {
}

flush() {
completersAndValues.forEach((cv) => cv[0].complete(cv[1]));
var toFlush = new List.from(completersAndValues);
completersAndValues = [];
toFlush.forEach((cv) => runAsync(() => cv[0].complete(cv[1])));
}

assertAllGetsCalled() {
Expand Down
3 changes: 2 additions & 1 deletion test/directives/ng_include_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ main() {
scope['template'] = 'tpl.html';
});

nextTurn(); // load the template from cache.
nextTurn(true); // load the template from cache.

expect(element.text()).toEqual('my name is Vojta');
})));

Expand Down
Loading