Knockout causing “slow running script” warning in

2019-01-28 11:24发布

问题:

I have a grid of observables and computed observables. The first row contains percentage rates used as a multiplier against the values in all the rows below. The user can edit the percentage rate value and Knockout handles all the cascading updates. I also need a separate textbox where the user can enter a new percentage rate that will be applied to each of the percentage rates in the grid.

Initial binding works fine and updating 1 percentage rate works is fine too.

The javascript warning occurs when the user enters a value in the textbox and I loop through the view model updating each of the percentage rates to match. The grid columns are actually monthly values so the loop to update the percentage rate only executes 12 times.

I tried throttle extender but it didn't solve the problem. Any ideas?

Update: not sure it will help, but I added some code

$("#NewRate").change(function (e) {
    var newRate = parseFloat($(this).val());
    for (var i = 0; i < 12; i++) {
        viewModel.resourceCategory.monthAmounts[i].amount(newRate);
    }
});

function ConvertToDate(jsonDateString) {
    var re = /-?\d+/;
    var m = re.exec(jsonDateString);
    return new Date(parseInt(m[0]));
}

function MonthAmount(amount, dateKey) {
    var self = this;
    self.amount = ko.observable(amount).extend({ throttle: 1 }); //using the throttle to avoid "long running script" warning in IE
    self.dateKey = ConvertToDate(dateKey);
    self.monthIndex = self.dateKey.getMonth();
}

function ResourceCategory(name, monthAmounts) {
    var self = this;
    self.name = name;

    self.monthAmounts = ko.utils.arrayMap(monthAmounts, function (monthAmount) {
        return new MonthAmount(monthAmount.Amount, monthAmount.DateKey);
    });

    self.totalAmount = ko.computed(function () {
        var sum = 0;
        for (var i = 0; i < self.monthAmounts.length; i++) {
            sum += parseFloat(self.monthAmounts[i].amount());
        }
        return sum.toFixed(2);
    }).extend({ throttle: 1 }); //using the throttle to avoid "long running script" warning in IE

    self.averageAmount = ko.computed(function () {
        return (self.totalAmount() / self.monthAmounts.length).toFixed(2);
    }).extend({ throttle: 1 }); //using the throttle to avoid "long running script" warning in IE

}
function ResourceCategoriesMonthTotal(monthIndex, resourceCategories) {
    var self = this;
    self.monthIndex = monthIndex;
    self.dateKey = new Date(new Date().getFullYear(), monthIndex, 1);
    self.amount = ko.computed(function () {
        var val = 0;
        for (var i = 0; i < resourceCategories.length; i++) {
            val += parseFloat(resourceCategories[i].monthAmounts[self.monthIndex].amount());
        }
        return (val).toFixed(2);
    }).extend({ throttle: 1 }); //using the throttle to avoid "long running script" warning in IE
}

self.resourceCategoriesMonthTotals = new Array();
for (var monthIndex = 0; monthIndex < 12; monthIndex++) {
    self.resourceCategoriesMonthTotals.push(new ResourceCategoriesMonthTotal(monthIndex, self.resourceCategories));
}

self.resourceCategoriesTotal = ko.computed(function () {
    var val = 0;
    for (var i = 0; i < self.resourceCategoriesMonthTotals.length; i++) {
        val += parseFloat(self.resourceCategoriesMonthTotals[i].amount());
    }
    return (val / self.resourceCategoriesMonthTotals.length).toFixed(2);
}).extend({ throttle: 1 }); //using the throttle to avoid "long running script" warning in IE

回答1:

Sounds like the problem is when you

loop through the view model updating each of the percentage rates to match

If so, then one answer for IE is to yield to the browser by using a timeout(0) call. When your JS resumes after the timeout, do the next iteration of the loop, then another timeout.

When I've done this, I only do the timeouts if I've sniffed that it is an IE browser. Otherwise, not needed.



回答2:

Ok, this stinks, but I think the problem is that I had this on my page:

<div data-bind="text: ko.toJSON($root)"></div>

After I removed that it didn't give me the “slow running script” warning.