yandex-ui / noscript

Noscript: JavaScript MVC Framework for building SPA
http://yandex-ui.github.io/noscript/
MIT License
34 stars 22 forks source link

ns.View + ns.Update: фикс кейса, когда мы пытаемся найти ноду для вложенного вида, тогда как родительский вид отрендерился в ошибочной моде #655

Open chestozo opened 6 years ago

chestozo commented 6 years ago

Есть, к примеру, такой лейаут

{
    parent: {
        nested: {}
    }
}

Вид parent зависит от модели m1.


Внутри метода ns.Update.prototype.render() есть такой код:

// начинаем цепочку с промиса, чтобы ловить ошибки в том числе и из _requestAllModels
// начинаем цепочку с промиса, чтобы ловить ошибки в том числе и из _requestAllModels
Vow.invoke(this._requestAllModels.bind(this))
    .then(function(result) {
        this._updateDOM();
        this._fulfill(result);
    }, this._reject, this)
    // еще один reject, чтобы ловить ошибки из #_updateDOM
    .then(null, this._reject, this);

Имеем дыру: между вызовом _requestAllModels и _updateDOM может вклиниться асинхронный js код. К примеру, мы запросили модель m1, она успешно вернулась и вообще всё идёт хорошо, метод _requestAllModels успешно завершается.

А где-то рядом вызвали:

setTimeout(function() {
    ns.Model.get('m1', {}).invalidate();
}, 0);

и так сложилось, что код выполнился после _requestAllModels, но перед _updateDOM. В этом случае parent рендерится в error моде. При этом, если не задать ns-view-error-content шаблон для parent, в котором будет ещё и рендеринг вида nested - получаем исключение Can't find node for 'nested'.


Идея фикса такая: