我正在尝试使用过程将数据从SQLServer绑定到Angularjs甘特图。该过程需要1-2秒才能运行,但绑定数据到甘特图需要120-150秒。这种情况正在发生,因为观察者正在观察一切。我想优化$ scope。$ digest(),以便观察者只观看必要的元素。我附上了探查器的截图并添加了我当前的代码,如果有人可以提供任何关于如何减少时间的建议,它将是一个很大的帮助。
Profiler数据:
HTML代码:
<div id="data_container" ng-if="homeCtrl.isRefreshClicked === true">
<div gantt api="homeCtrl.registerApi" data="homeCtrl.chartData"
headers-formats="homeCtrl.headersFormats"
view-scale="homeCtrl.scale"
column-width="homeCtrl.ganttColumnWidth"
current-date="homeCtrl.currentDate"
from-date="homeCtrl.ganttFromDate"
to-date="homeCtrl.ganttToDate"
max-height="homeCtrl.ganttHeight && homeCtrl.maxGanttHeight || 0"
style="background-color: white; width: 100%; padding-right: 15px; margin: 7px 0; min-height: 400px;">
<gantt-tree></gantt-tree>
<gantt-groups></gantt-groups>
<gantt-tooltips></gantt-tooltips>
<gantt-bounds></gantt-bounds>
<gantt-progress></gantt-progress>
<gantt-sortable></gantt-sortable>
<gantt-movable></gantt-movable>
<gantt-draw-task></gantt-draw-task>
<gantt-resize-sensor></gantt-resize-sensor>
</div>
Homecontroller.js
homeService.getGanttData(input_filters).success(function (asyncData) {
var result = asyncData;
homeCtrl.dbChartData = jQuery.extend(true, [], asyncData);
//var UniqueNames = $.unique(result.map(function (d) { return d.EquipmentID; }));
var UniqueNames = [];
for (i = 0; i < result.length; i++) {
if (UniqueNames.indexOf(result[i].EquipmentID) === -1) {
UniqueNames.push(result[i].EquipmentID);
}
}
var chartData = [];
for (var i = 0; i < UniqueNames.length; i++) {
var wantedData = result.filter(function (j) {
return j.EquipmentID === UniqueNames[i];
});
chartData.push({ name: wantedData[0].Location, tasks: wantedData });
}
for (var i = 0; i < chartData.length; i++) {
var tasksList = chartData[i].tasks;
for (var j = 0; j < tasksList.length; j++) {
var taskFromDate = tasksList[j].from;
var taskToDate = tasksList[j].to;
Math.abs(tasksList - taskFromDate);
}
}
var fromDate = $("#start_date_picker input").val().split('/');
homeCtrl.ganttFromDate = new Date(fromDate[2], fromDate[0] - 1, fromDate[1]);
homeCtrl.ganttToDate = new Date(new Date(homeCtrl.ganttFromDate).setMonth(homeCtrl.ganttFromDate.getMonth() + parseInt(homeCtrl.selectedDuration.Desc.split(" ")[0])));
homeCtrl.chartData = chartData;
homeCtrl.ganttSortValue = false;
homeCtrl.ganttDataSort();
homeCtrl.changeSelectedPeriod(homeCtrl.selectedPeriod);
$timeout(function () {
notifier.hideLoadingIndicator();
}, 5000);
}).error(function (asyncData) {
homeCtrl.showCustomAlertMsgWithAlertTextCenter(asyncData);
});
}, 100);
Angular.js $ scope。$ digest():
$digest: function() {
var watch, value, last, fn, get,
watchers,
length,
dirty, ttl = TTL,
next, current, target = this,
watchLog = [],
logIdx, asyncTask;
beginPhase('$digest');
// Check for changes to browser url that happened in sync before the call to $digest
$browser.$$checkUrlChange();
if (this === $rootScope && applyAsyncId !== null) {
// If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
// cancel the scheduled $apply and flush the queue of expressions to be evaluated.
$browser.defer.cancel(applyAsyncId);
flushApplyAsync();
}
lastDirtyWatch = null;
do { // "while dirty" loop
dirty = false;
current = target;
while (asyncQueue.length) {
try {
asyncTask = asyncQueue.shift();
asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
} catch (e) {
$exceptionHandler(e);
}
lastDirtyWatch = null;
}
traverseScopesLoop:
do { // "traverse the scopes" loop
if ((watchers = current.$$watchers)) {
// process our watches
length = watchers.length;
while (length--) {
try {
watch = watchers[length];
// Most common watches are on primitives, in which case we can short
// circuit it with === operator, only when === fails do we use .equals
if (watch) {
get = watch.get;
if ((value = get(current)) !== (last = watch.last) &&
!(watch.eq
? equals(value, last)
: (typeof value === 'number' && typeof last === 'number'
&& isNaN(value) && isNaN(last)))) {
dirty = true;
lastDirtyWatch = watch;
watch.last = watch.eq ? copy(value, null) : value;
fn = watch.fn;
fn(value, ((last === initWatchVal) ? value : last), current);
if (ttl < 5) {
logIdx = 4 - ttl;
if (!watchLog[logIdx]) watchLog[logIdx] = [];
watchLog[logIdx].push({
msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
newVal: value,
oldVal: last
});
}
} else if (watch === lastDirtyWatch) {
// If the most recently dirty watcher is now clean, short circuit since the remaining watchers
// have already been tested.
dirty = false;
break traverseScopesLoop;
}
}
} catch (e) {
$exceptionHandler(e);
}
}
}
// Insanity Warning: scope depth-first traversal
// yes, this code is a bit crazy, but it works and we have tests to prove it!
// this piece should be kept in sync with the traversal in $broadcast
if (!(next = ((current.$$watchersCount && current.$$childHead) ||
(current !== target && current.$$nextSibling)))) {
while (current !== target && !(next = current.$$nextSibling)) {
current = current.$parent;
}
}
} while ((current = next));
// `break traverseScopesLoop;` takes us to here
if ((dirty || asyncQueue.length) && !(ttl--)) {
clearPhase();
throw $rootScopeMinErr('infdig',
'{0} $digest() iterations reached. Aborting!\n' +
'Watchers fired in the last 5 iterations: {1}',
TTL, watchLog);
}
} while (dirty || asyncQueue.length);
clearPhase();
while (postDigestQueue.length) {
try {
postDigestQueue.shift()();
} catch (e) {
$exceptionHandler(e);
}
}
},