, ! angular webapps, .
, ngRepeat google
$scope. $watchCollection, . ( .) $watchCollection setTimeout .
ngRepeat. myRepeat.
app.directive('myRepeat', function ($compile) {
return {
restrict:'A',
transclude: 'element',
priority: 1000,
terminal: true,
$$tlb: true,
compile: function ($element, $attr) {
var expression = $attr.myRepeat;
var ngRepeatEndComment = $compile.$$createComment('end myRepeat', expression);
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
var rhs = match[2];
return function ($scope, $element, $attr, ctrl, $transclude) {
$scope.$watchCollection(rhs, function myRepeatAction(collection) {
$transclude(function(clone, scope) {
clone[clone.length++] = clone;
});
});
}
}
}
});
watchCollection, . $watchCollection setTimeout, .
angular.js, watchCollection => $watch => $evalAsync => $browser.defer => setTimeout
$ .
$source.defer
, .:)
myRepeat.
github angular.js.
P.S , angular - 1.5.3, 1.5.3.
async
setTimeout.
, ,
function dir1(callback) {
console.log('compile dir1');
callback();
console.log('link dir1');
}
function dir2() {
console.log('compile dir2');
console.log('link dir2');
}
dir1(dir2);
ngRepeat, ,
function dir1(callback) {
console.log('compile dir1');
callback();
console.log('link dir1');
}
function dir2() {
console.log('compile dir2');
console.log('link dir2');
}
function myRepeat(callback) {
return function() {
setTimeout(callback, 0);
}
}
dir1(myRepeat(dir2));
, 2. , ?
setTimeout ( 0).
, ,, , link dir1.
1. compile dir1
2. setTimeout(execute after 0 second)
3. link dir1(current block is running, so do this first)
4. compile dir2 (it free now, invoke the callback)
5. link dir2
, .
setTimeout John Resig javascript.