¿Hay una manera de decirle a un knockout que espere para recalcular los valores calculados hasta que se haya definido el modelo de vista?

Tengo un modelo de vista complejo que es un par de cientos de líneas de código javascript con una buena cantidad de propiedades observables, propiedades observables calculadas, propiedades y funciones observables calculadas computables de escritura. Por lo tanto, gestionar esto es un reto.

Un problema molesto con el que he tenido que lidiar es que los observables calculados se calculan de forma inmediata cuando se define. Por lo tanto, el uso de variables que aún no se han definido en el modelo de vista en el momento de definir lo observable conduce a errores que indican que la variable no se ha definido. Es ... justo más tarde en el archivo.

Aquí hay un ejemplo artificial:

function ViewModel1​(args) {
    var self = this;

    self.firstName = ko.observable(args.firstName);
    self.lastName = ko.observable(args.lastName);
    self.fullName = ko.computed(function () {
        return self.firstName() + ' ' + self.lastName();
    });
}

function ViewModel2​(args) {
    var self = this;

    self.fullName = ko.computed(function () {
        // uh oh, where's firstName?
        return self.firstName() + ' ' + self.lastName();
    });
    self.firstName = ko.observable(args.firstName);
    self.lastName = ko.observable(args.lastName);
}

UtilizandoViewModel1 Trabajará sin problemas. En el puntofullName se define,firstName ylastName Se define por lo que funciona como se espera. UtilizandoViewModel2 no trabajará. Habría un error en la función computada indicandofirstName no está definido.

Lo que he estado haciendo hasta ahora era asegurar que todos los observables calculados se definan después de que se hayan definido todas las variables dependientes. El problema con esto es que al hacerlo, las cosas se definen en lugares aparentemente aleatorios cuando preferiría mantener las variables relacionadas definidas juntas.

Una buena solución que he encontrado es definir un conjunto observable de "inicialización" paratrue y haga que todos los observables computados prueben si aún se está inicializando, calcule y devuelva el valor cuando no lo esté. De esa manera, los intentos de acceder a la variable actualmente no definida no se harán.

function ViewModel3(args) {
    var self = this;
    var initializing = ko.observable(true);

    self.fullName = ko.computed(function () {
        if (!initializing()) {
            return self.firstName() + ' ' + self.lastName();
        }
    });
    self.firstName = ko.observable(args.firstName);
    self.lastName = ko.observable(args.lastName);

    initializing(false);
}

Pero esto no será muy práctico en mi caso sin embargo. Tengo muchos observables computados, así que hacer esto en todos ellos hará que esté muy hinchado, recuerde que tengo muchos de estos. La regulación no parece hacer una diferencia.

¿Hay una manera de decirle a un nocaut que espere antes de intentar calcular los valores de los observables calculados? ¿O hay una mejor manera de estructurar mi código para lidiar con esto?

Probablemente podría realizar algunas funciones de ayuda para administrar la lógica de inicialización, pero todavía tendría que alterar todas las definiciones observables calculadas. Supongo que puedo anular el nocaut del parche para agregar esta lógica de inicialización, ya que no estoy consciente de que el nocaut tenga tales opciones que podría hacer. He mirado la fuente de los observables computados anteriormente, pero no sé si ya existe una configuración en otro lugar.

demo jsfiddle

Respuestas a la pregunta(1)

Su respuesta a la pregunta