Если "повесить" зависимость некоторого атрибута на колонку, в методе-обработчике зависимости изменять значение колонки-зависимости - вполне предсказуемо получить рекурсивный вызов.
Но обычно цепочка рекурсивных вызовов пресекается установкой флага, или внедрением проверок, которые гарантированно не пройдут при повторном вызове, что в свою очередь обеспечит выполнение рекурсивного вызова без изменения целевого значения.
В данном случае, не зависимо от механики предусмотренной в методе-обработчике, его вызов уходит в рекурсию в том случае если во время его исполнения было изменено значение зависимой колонки.
н/п
...
"SameHandler": {
dependencies: [
{
//поле с типом "Дата-время"
columns: ["TargetColumn"],
methodName: "SameHandlerControl"
}
]
},
...
...
"SameHandlerControl": function() {
if (window.foo) {
window.foo = false;
} else {
window.foo = true;
this.set("TargetColumn", new Date());
}
},
так вот несмотря на то, что при повторном вызове обработчика, выполнение уходит в ветку
if (window.foo) {
window.foo = false;
...
после чего, рекурсивные вызовы, по идее, должны закончиться т.к. значение "TargetColumn" более не меняется, по факту вызовы SameHandlerControl уходят в бесконечную рекурсию
Как этого избежать ?
Почему так происходит ?
PS: классический кейс "самоконтроля поля ввода" - поле реагирует на изменение своего значения вызовом обработчика, который производит проверки и вычисления с введенным значением, по необходимости корректируя/восстанавливая свое собственное значение, предотвращая рекурсивный вызов обработчика.
Нравится
Здравствуйте
Интересный случай. Глубоко не копал, но причина вроде бы в последовательности вызова
меняя this.set("TargetColumn", new Date());, вы "дергаете" SameHandlerControl, т.к. атрибут связан с колонкой. И поскольку перед "самовызовом" метода вы меняете флаг выхода, то получается замкнутый цикл
попробуйте вызвать window.foo = true; ПОСЛЕ this.set("TargetColumn", new Date());
мой тестовый код, на котором нет вечного цикла
[javascript]
define("UsrSection1Page", [], function() {
return {
entitySchemaName: "UsrSection",
attributes: {
"SameHandler": {
dependencies: [
{
columns: ["UsrName"],
methodName: "SameHandlerControl"
}
]
}
},
methods: {
"SameHandlerControl": function() {
var n = this.get("UsrName");
if (window.foo) {
window.foo = false;
} else {
//window.foo = true;
this.set("UsrName", n + window.foo);
window.foo = true;
}
}
},
...
[/javascript]
Я решил, проблему "отложенным вызовом на 100 мс." смены атрибута который приводит к вызову обработчика в рекурсии
[javascript]
...
setTimeout(function(){
this.set("TargetColumn", new Date())
}.bind(this), 100);
...
[/javascript]
т.е. как только выполнение обработчика завершается корректно - повторный вызов из отложенной функции уже корректно ловит "флаг" и его обрабатывает.
PS: создается такое впечатление что срабатывание обработчиков - псевдосинхронное, т.е. this.set банально "стакает" текущий контекст, и функция вызывается повторно, не завершившись в предыдущий раз.