KnockoutJS catch errors Binding

Я хочу поймать ошибку, исправить ее и продолжить выполнение программы. http://jsfiddle.net/Gthv9/12/

Но я не могу этого сделать!

Если вы нажмете: "re Check On Model1", "re Check On Model3" - это нормально.

Если вы нажмете: "re Check On Model1", "re Check On Model2", "re Check On Model3" - есть ошибка.

Uncaught Error: Unable to parse bindings.
Message: ReferenceError: name3 is not defined;
Bindings value: text: name3 

Почему?

Я завернул код проблемы в блок try-catch (viewModel.recheckData2()), но приложение сбой при нажатии viewModel.recheckData3()!

Я знаю, что нокаутJS сохраняет состояние ошибки (новая модель2()), но не знаю, что я должен делать.

Как правильно поймать ошибку?

Спасибо!

Ответ 1

Я не уверен, что понимаю вашу точную цель, но Knockout перестанет связываться, когда он столкнется с этим типом проблемы.

Если ваша проблема - это просто переменные undefined, то один трюк, который вы можете использовать, - это привязка к $data.name3, а не только name3. Доступ к свойству undefined из допустимого объекта не вызывает ошибки.

Если вы действительно хотите что-то более надежное, вы можете рассмотреть возможность использования поставщика привязки.

Например, вы можете написать быструю оболочку для реального поставщика привязки, например:

var ErrorHandlingBindingProvider = function() {
    var original = new ko.bindingProvider(); 

    //determine if an element has any bindings
    this.nodeHasBindings = original.nodeHasBindings;

    //return the bindings given a node and the bindingContext
    this.getBindings = function(node, bindingContext) {
        var result;
        try {
            result = original.getBindings(node, bindingContext);
        }
        catch (e) {
            if (console && console.log) {
                console.log("Error in binding: " + e.message);   
            }
        }

        return result;
    };
};

ko.bindingProvider.instance = new ErrorHandlingBindingProvider();

Это приведет к сбою ошибок, их регистрации и продолжению. Конечно, элемент, который имел это "плохое" связывание, не связан. Если есть какой-то известный способ, с которым вы хотите справиться, тогда вы можете добавить эту логику после обнаружения ошибки. Возможно, вы хотите проверить этот элемент (node) и bindingContext, чтобы определить, что нужно сделать.

Образец: http://jsfiddle.net/rniemeyer/KxXqs/

UPDATE: версия 3.0+, в которой ошибки ловушек/журналов в синтаксисе связывания, а также ошибки, когда фактически оценивается значение границы. http://jsfiddle.net/rniemeyer/ecbn1dmy/

Ответ 2

Я добавил еще одну строку обработчику ошибок из @RPNiemeyer, чтобы консоль node, вызывающая ошибку в блоке catch, позволяет очень легко найти ошибку на сложной странице:

if (console && console.log) {
            console.log("Error in binding: " + e.message);
            console.log("Node causing error:");
            console.log(node);
        }