계산 된 속성 함수를 강제 실행


80

계산 된 속성이 주어지면

vm.checkedValueCount = ko.computed(function(){
  var observables = getCurrentValues();  //an array of ko.observable[]
  return _.filter(observables, function(v) { return v() }).length;
});

getCurrentValues ​​()가 코드의 다른 곳에서 수정 된 (그리고 observableArray보다 더 복잡한 구조에서 온) 다른 관찰 가능 집합을 반환 할 수 있다고 가정합니다.

checkedValueCount언제든지 업데이트 해야 합니다.

  • 종속성 중 하나가 변경됩니다.
  • getCurrentValues ​​()는 다른 관찰 가능 항목 집합을 반환합니다.

문제는 ko.computed마지막으로 반환 된 값을 기억하고 종속성이 업데이트 될 때만 업데이트 되는 것 같습니다. 이것은 첫 번째 경우를 처리하지만 후자는 처리하지 않습니다.

내가 찾고있는 것은 checkedValueCount를 강제로 다시 실행하는 방법입니다. 다음과 같이 사용할 수있는 것 :

changeCurrentValues();
vm.checkeValueCount.recalculate();

가장 간단하게 말하면

a = ko.computed(function() { return Math.random() })

어떻게 강제로 a()두 번 호출 하여 다른 값을 반환 할 수 있습니까 ?


업데이트 된 "재 작성된"답변을 참조하십시오.
Josh

답변:


116

내 첫 번째 답변이 귀하의 요점을 놓치고 귀하의 문제를 해결하지 못할 것임을 깨달았습니다.

문제는 계산이 재평가를 강요하는 관찰 가능 항목이있는 경우에만 재평가한다는 것입니다. 계산 된 항목을 재평가하도록 강제하는 기본 방법은 없습니다.

그러나 더미 관찰 가능한 값을 만든 다음 구독자에게 변경되었음을 알리면 일부 해커로이 문제를 해결할 수 있습니다.

(function() {

    var vm = function() {
        var $this = this;

        $this.dummy = ko.observable();

        $this.curDate = ko.computed(function() {
            $this.dummy();
            return new Date();
        });

        $this.recalcCurDate = function() {
            $this.dummy.notifySubscribers();
        };        
    };

    ko.applyBindings(new vm());

}());​

다음은 이 접근 방식을 보여주는 Fiddle입니다.


아, 이거 해봤는데 잘못 연결 했나봐요. 이 모습은 해키하지만 좋은 (좋은의 충분한 나는 일에 할 수 있도록 ko.computed 확장 할 수 있음
조지 마우어

항상 그렇듯이 더 간단한 것이 최고입니다.
Henry Rodriguez

1
이것은 관찰 할 수없는 대규모 데이터 배열을 변경하고 변경 후에 데이터의 일부를 표시해야 할 때 유용합니다.
Marek Bar

1
notifySubscribers () 사용은 좋은 것입니다. 난수를 만들고 dummy () 값으로 설정하는 것보다 낫다
efreed

9

사용자에 따라 모든 관찰 가능 항목을 강제로 다시 계산 하는 방법 이 있습니다.

getCurrentValues.valueHasMutated()

9
계산에는이 방법이 없습니다
George Mauer 2014

getCurrentValues(); //an array of ko.observable[]
Rustam

아, 알겠습니다. 당신은 계산 된 의존성 인 observable을 찾아서 그것을 valueHasMutated메서드 라고 부르는 것 입니다. 이것은 위의 Josh의 대답과 근본적으로 다르지 않습니다. 사실 그것은 당신이 무엇을 참조하고 있는지 그리고 그 참조가 관찰 가능하다는 것을 알도록 강요합니다.
George Mauer 2014

2
그럼에도 불구하고이 함수는 독자를위한 옵션으로 남아 있기 때문에 언급하는 것이 좋습니다. 그러나 누군가가이 함수가 notifySubscribers ()와 상호 교환 될 수있는 경우에 대해 승인 된 답변을 업데이트 할 수 있고 어느 쪽이든 패널티 나 이점이 있는지 여부를 확인할 수 있습니다.
Shaun Wilson

4

이 답변은 @josh가 준 것과 개념적으로 동일하지만 더 일반적인 래퍼로 제공됩니다. 참고 :이 버전은 '쓰기 가능'계산 용입니다.

Typescript를 사용하고 있으므로 먼저 ts.d 정의를 포함했습니다. 따라서 당신과 관련이 없다면이 첫 번째 부분을 무시하십시오.

interface KnockoutStatic
{
    notifyingWritableComputed<T>(options: KnockoutComputedDefine<T>, context ?: any): KnockoutComputed<T>;
}

알림 쓰기 가능 계산

쓰기 가능한 래퍼 observable것을 항상 더 관찰 가능한이의 결과로 업데이트되지 않은 경우에도 - 가입자의 원인 통지한다write 전화

그냥 교체 function<T> (options: KnockoutComputedDefine<T>, context)와 함께 function(options, context)당신이 타이프 라이터를 사용하지 않는 경우.

ko.notifyingWritableComputed = function<T> (options: KnockoutComputedDefine<T>, context)
{
    var _notifyTrigger = ko.observable(0);
    var originalRead = options.read;
    var originalWrite = options.write;

    // intercept 'read' function provided in options
    options.read = () =>
    {
        // read the dummy observable, which if updated will 
        // force subscribers to receive the new value
        _notifyTrigger();   
        return originalRead();
    };

    // intercept 'write' function
    options.write = (v) =>
    {
        // run logic provided by user
        originalWrite(v);

        // force reevaluation of the notifyingWritableComputed
        // after we have called the original write logic
        _notifyTrigger(_notifyTrigger() + 1);
    };

    // just create computed as normal with all the standard parameters
    return ko.computed(options, context);
}

이에 대한 주요 사용 사례는 read함수에 의해 '방문'되는 관찰 가능 항목의 변경을 트리거하지 않는 무언가를 업데이트하는 경우입니다 .

예를 들어 LocalStorage를 사용하여 일부 값을 설정하고 있지만 재평가를 트리거하기 위해 관찰 가능한 항목에는 변경 사항이 없습니다.

hasUserClickedFooButton = ko.notifyingWritableComputed(
{
    read: () => 
    {
        return LocalStorageHelper.getBoolValue('hasUserClickedFooButton');
    },
    write: (v) => 
    {
        LocalStorageHelper.setBoolValue('hasUserClickedFooButton', v);        
    }
});

모든 내가 변화를 필요로합니다이었다 ko.computedko.notifyingWritableComputed다음 모든 자체 처리합니다.

내가 전화 할 때 hasUserClickedFooButton(true) 하면 '더미'Observable이 증가하여 LocalStorage의 값이 업데이트 될 때 구독자 (및 구독자)가 새 값을 얻도록 강제합니다.

(참고 : notify: 'always'익스텐더가 여기에서 옵션 이라고 생각할 수 있지만 이는 다른 것입니다).


읽기만 가능한 계산 된 관찰 가능 항목에 대한 추가 솔루션이 있습니다.

ko.forcibleComputed = function(readFunc, context, options) {
    var trigger = ko.observable().extend({notify:'always'}),
        target = ko.computed(function() {
            trigger();
            return readFunc.call(context);
        }, null, options);
    target.evaluateImmediate = function() {
        trigger.valueHasMutated();
    };
    return target;
};


myValue.evaluateImmediate();

@mbest 댓글에서 https://github.com/knockout/knockout/issues/1019 .


가치가 없다는 게 무슨 뜻입니까? 이것으로 전환하기 전에 작동 했습니까? 지연된 업데이트를 사용하고 있습니까 (전역 설정). Observable을 업데이트하고 즉시 값을 사용할 수있을 것으로 예상하면 충돌 이 있을 수 있음을 깨달았습니다 . 그렇다면 내 메서드에 ko.tasks.runEarly ()를 추가해보십시오.
Simon_Weaver

1

getCurrentValues ​​()가 코드의 다른 곳에서 수정 된 다른 관찰 가능 집합을 반환 할 수 있다고 가정합니다.

getCurrentValues ​​()가 함수라고 가정합니다. 그것을 계산할 수 있다면, 당신의 checkedValueCount는 마술처럼 작동하기 시작할 것입니다.

getCurrentValues를 함수 대신 계산되도록 만들 수 있습니까?


나는 실제 시나리오를 지나치게 단순화하고 있지만 확실하다고 가정 해 봅시다. getCurrentValues ​​() 내부에서 반환해야하는 트리 뷰의 노드를 결정하기 위해 다른 데이터를 슬라이스하고 다이 싱하고 있습니다. 문제는 함수가 다른 관찰 가능한 값을 반환 할 수 있고 그것을 선택하기 위해 계산 된 값이 필요하다는 것입니다. 기본적으로 정확히 문서가 동적 종속성에 대해 이야기하는 내용이지만 즉석에서 추가되는 복잡성으로 인해
George Mauer

"슬라이싱 및 다이 싱"이 관찰 가능 항목을 기반으로했다면 차이가있을 것입니다. 예를 들어 슬라이싱 및 다이 싱이 .IsChecked () == true 인 노드라고 가정 해 보겠습니다. 그런 다음 모든 노드를 평가하고 .IsChecked ()로 노드를 반환하는 .currentValues ​​()라는 계산 된 값을 갖게됩니다. 관찰 가능한 속성에 대해 슬라이싱 및 다이 싱을 수행 할 수 있습니까?
유다 가브리엘 희망 고

나는 당신이 유다에 대해 무슨 말을하는지 잘 모르겠습니다. 모든 단일 호출이 제 경우에는 코를 관찰 할 수는 없습니다. 그러나 더 중요한 것은 그것이 어떻게 중요 할 수 있는지 모르겠습니다. 녹아웃은 어떤 반성도하지 않습니다. 당신이 호출 한 클로저 (나는 확인하지 않았지만 자바 스크립트가 완전히 lisp-land로 들어 가지 않는 한 불가능합니다). 계산 된 모든 작업은 호출 된 관찰 가능 항목을 기껏해야 추적 할 수 있습니다.
George Mauer 2012

-1

계산 된 항목을 강제로 업데이트 할 수있는 직접적인 방법이 없기 때문에 toForceComputedUpdate라는 관찰 가능 항목을 만들었으며 계산 된 함수 내에서 호출하여 계산 된 항목이 업데이트를 수신 한 다음 강제 업데이트를 위해 다음과 같이 호출합니다. toForceComputedUpdate (Math .random)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.