удалить подозрения в дюрандале?

При работе с Durandal и Knockout у меня возникли проблемы с подпиской на свойства. По сути, в моем методе 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 (к сожалению, я бы предпочел использовать чистый js). То, как машинописный текст переводит свой код в чистый 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.

Подписка Knockout observable предоставляет функцию .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 в свою активированную функцию - тогда он будет загружаться только при первой загрузке представления.

person Chris Dixon    schedule 11.07.2013
comment
спасибо за отзыв, код метода 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 при вызове viewAttached, чтобы подписки работали. - person Chris Dixon; 11.07.2013
comment
хорошая попытка, но не работает. другая библиотека js устанавливает значение в разметке, поэтому код подписки снова запускается (после того, как для bool установлено значение false). Итак, я возвращаюсь к своему первоначальному вопросу, как удалить код подписки? как я могу сказать, что подписка = ноль? - person Rolando; 11.07.2013