01.01.2015 Views

build_your_own_angularjs_sample

build_your_own_angularjs_sample

build_your_own_angularjs_sample

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Build Your Own Angular Chapter 1. Scopes And Digest<br />

Scope.prototype.$digest = function() {<br />

var ttl = 10;<br />

var dirty;<br />

this.$$lastDirtyWatch = null;<br />

do {<br />

while (this.$$asyncQueue.length) {<br />

var asyncTask = this.$$asyncQueue.shift();<br />

asyncTask.scope.$eval(asyncTask.expression);<br />

}<br />

dirty = this.$$digestOnce();<br />

if ((dirty || this.$$asyncQueue.length) && !(ttl--)) {<br />

throw "10 digest iterations reached";<br />

}<br />

} while (dirty || this.$$asyncQueue.length);<br />

};<br />

Now we can be sure the digest will terminate, regardless of whether it’s running because<br />

it’s dirty or because there’s something in its async queue.<br />

Scope Phases<br />

Another thing $evalAsync does is to schedule a $digest if one isn’t already ongoing. That<br />

means, whenever you call $evalAsync you can be sure the function you’re deferring will be<br />

invoked “very soon” instead of waiting for something else to trigger a digest.<br />

For this to work there needs to be some way for $evalAsync to check whether a $digest<br />

is already ongoing, because in that case it won’t bother scheduling one. For this purpose,<br />

Angular scopes implement something called a phase, which is simply a string attribute in<br />

the scope that stores information about what’s currently going on.<br />

As a unit test, let’s make an expectation about a field called $$phase, which should be<br />

“$digest” during a digest, “$apply” during an apply function invocation, and null otherwise:<br />

test/scope_spec.js<br />

it("has a $$phase field whose value is the current digest phase", function() {<br />

scope.aValue = [1, 2, 3];<br />

scope.phaseInWatchFunction = undefined;<br />

scope.phaseInListenerFunction = undefined;<br />

scope.phaseInApplyFunction = undefined;<br />

scope.$watch(<br />

function(scope) {<br />

scope.phaseInWatchFunction = scope.$$phase;<br />

return scope.aValue;<br />

},<br />

function(newValue, oldValue, scope) {<br />

32 ©2014 Tero Parviainen Errata / Submit

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!