премахване на suscrptions ko в durandal?

Работейки с дюрандал и нокаут, имам някои проблеми с абонамента за имотите. По принцип в моя метод viewAttached имам някакъв абонамент за наблюдаеми свойства, които работят много добре при първото зареждане на моя изглед. При втория път, когато заредя изгледа, имам някои проблеми поради това, че кодът вътре в абонаментите се изпълнява (нещо, което не искам). Кодът е нещо такова:

export var viewAttached = function (view) {


toDate.subscribe(function (newValue) {      
    isLoading(true);
    return datacontext.getData(newValue).then(function () {
        isLoading(false);
    });
});

fromDate.subscribe(function (newValue) {       
    isLoading(true);
    return datacontext.getData(newValue).then(function () {
        isLoading(false);
    });
});
}

Кодът вътре в абонамента се изпълнява в момента, за да зареди моя изглед за втори път, какво не е наред. Бих искал да знам дали е възможно да премахна абонаментите за това свойство след това, за да разтоваря изгледа си. Това възможно ли е? възможно ли е да знаете кога даден изглед се разтоварва?. всяка помощ се оценява.

АКТУАЛИЗАЦИЯ: Опитах се да премахна абонамента във функцията за активиране (вижте документите на durandal), но кодът за абонамент все още е там.

export function activate() {      
   //remove suscriptions
    toDate.subscribe(function (newValue) {
     //do nothing
    });

    fromDate.subscribe(function (newValue) {
     //do nothing
    });   
}

АКТУАЛИЗАЦИЯ: fromDate и ToDate са декларирани като (използвам машинопис)

export var fromDate = <any>ko.observable();
export var toDate = <any>ko.observable();

fromDate и toDate и зададени по подразбиране на метода за активиране:

function loadInitData() {   
   var focusDate = ko.observable(selectedDate);
   fromDate(firstDayOfMonth(focusDate));
   toDate(getLastDayOfMonth(focusDate));
   loadFilterLookups();
   loadRegistrations();   
}


export function activate() {      
   loadInitData();
}

person Rolando    schedule 11.07.2013    source източник
comment
Има ли причина subscribe да не е настроен веднага след дефинирането на toDate и fromDate?   -  person RainerAtSpirit    schedule 11.07.2013
comment
причината беше, защото в моя метод за активиране се обаждам на моята услуга със стойности по подразбиране за fromDate и toDate. така че това, което направих, беше: 1) Зададох променливи със стойности по подразбиране 2) Извиках моите услуги 3) Добавих абонаменти за фючърсни промени в моя филтър от потребителския интерфейс. проверете тази публикация: stackoverflow.com/questions/17178632/   -  person Rolando    schedule 11.07.2013
comment
Можете ли да покажете контура на AMD, където toDate и fromDate са дефинирани и дали модулът връща сингълтон или конструкторска функция? Ако използвате сингълтън, имате ли включен cacheViews: true във вашия изглед?   -  person RainerAtSpirit    schedule 12.07.2013
comment
За съжаление използвам TypeScript (казвам за съжаление, защото бих предпочел да използвам pur js). Начинът, по който typescript превежда кода си в чист js, създава зависимост, наречена експортиране. така че декларацията на fromDate и toDate е: exports.fromDate = ko.observable(); exports.toDate = ko.observable();   -  person Rolando    schedule 13.07.2013
comment
За съжаление не владея достатъчно добре TypeScript ;-), така че ако можете да добавите компилирания JavaScript вместо това. Бих искал да видя JS, който дефинира addDate и fromDate и изискването define около него.   -  person RainerAtSpirit    schedule 16.07.2013


Отговори (2)


Основното решение

Попитахте как човек може да отпише абонамент за нещо, абонирано за KnockoutJS.

Наблюдаваните абонаменти за нокаут разкриват функция .dispose() само за това.

Когато се абонирате:

var subscription = toDate.subscribe(function (newValue) {
 //do nothing
});
 

Почисти:

subscription.dispose();

Ако искате това за множество абонаменти, може да помислите да ги поставите в масив и след това да изчистите след всички тях, нещо като

var subs = [];
function subSafe(observable,function){
    subs.push(observable.subscribe(function));
}
function unsubscribeAll(){
    subs.forEach(function(subscription){
        subscription.dispose();
    });
}

Самостоятелен пример.

Да кажем, че имаме два бутона и стойност, един бутон увеличава тази стойност. Имаме слушател за промяна на стойността, който има alert. Когато щракнем върху втория бутон, абонаментът се премахва.

HTML:

<button data-bind="click: $root.inc">Inc</button>
<button data-bind="click: $root.unsub">Remove subscription</button>

JavaScript:

var vm = {
    val:ko.observable(0),
    inc:function(){
        vm.val(vm.val()+1);
    },
};
vm.sub = vm.val.subscribe(function(newVal){
   alert("Increased to "+newVal); 
});
vm.unsub = function(){
    vm.sub.dispose();    
}
ko.applyBindings(vm);

Ето кратка цигулка, илюстрираща процеса

person Benjamin Gruenbaum    schedule 15.07.2013

Просто - преместете вашия ViewAttached код във вашата активирана функция - тогава той ще се зареди само при първото зареждане на View.

person Chris Dixon    schedule 11.07.2013
comment
благодаря ви за обратната връзка, кодът за метода viewAttached се изпълнява веднъж. Проблемът е, че кодът вътре в абонамента се изпълнява всеки път (може да мисля, че свойствата задържат или помнят абонаментите). Едно нещо, което се опитах да направя, е да заменя функцията за абонамент с нищо във функцията за активиране (както знаете, функцията за активиране се изпълнява преди функцията viewattached, според документацията на Durandal). виж моята актуализация. - person Rolando; 11.07.2013
comment
Имате ли нещо, задаващо тези стойности fromDate и toDate във функция, която се изпълнява всеки път при зареждане? Това е единственият начин, по който мога да видя това да се случва - абонаментът трябва да бъде ударен само когато стойността се промени. - person Chris Dixon; 11.07.2013
comment
да, имам го и не мога да направя нищо по въпроса. преди да извикам datacontext, трябва да задам филтър по подразбиране. Бих искал да имам моя код към тази поръчка. 0) Премахнете абонаментите, ако съществуват. 1) Задайте дати по подразбиране 2) Добавете абонаменти. - person Rolando; 11.07.2013
comment
Или имайте променлива, която е зададена на true при активиране, след това задайте вашите елементи и проверете вашите абонаменти, за да видите дали тази променлива е false. Ако е вярно, тогава не стартирайте абонаментния код. След това задайте тази променлива на false, когато се извиква viewAttached, така че абонаментите да работят. - person Chris Dixon; 11.07.2013
comment
добър опит, но не работи. друга js библиотека задава стойността в маркирането, така че кодът за абонамент се изпълнява отново (след като зададете bool на false). така че се връщам към първоначалния си въпрос, как да премахна кода за абонамент? как мога да кажа suscription= null? - person Rolando; 11.07.2013