2014-12-03 102 views
2

我一直在瘋狂試圖找出這一個。在異步調用完成後,我看到了大量令人困惑和難以實現的在Knockout中填充計算可觀察值的例子,但似乎無法使用模塊揭示模式使其工作。推遲異步計算觀察

我想創建一個只讀的可觀察,因爲這是我需要的。如果我不需要匿名函數來運行請求,我甚至不會創建觀察值。這裏是我的視圖模型:

eh.vm.skills = function() { 

    //#region Public Variables 

    var skills = ko.computed({ 
      read: function() { 
       $.get("http://horodyski.me/api/skills", function (data) { 
        return data; 
       }); 
      }, 
      deferEvaluation: true 
     }), 
    //#endregion 


    //#region Public Interface 

    return { 
     skills: skills 
    } 

    //#endregion 
}; 

這是HTML綁定:

<ul class="skills skills-top" id="skills" data-bind="foreach: skills"> 
    <li> 
     <i data-bind="text: $index"> </i> 
     <span data-bind="text: $data.Title"></span> 
    </li> 
</ul> 
<script src="//cdn.horodyski.me/js/vm.js"></script> 
<script> 
    ko.applyBindings(eh.vm.skills, $("#skills")[0]); 
</script> 

我想要做的是創造skills變量,取數據,並將其返回。數據已經以數組的形式出現(例如:[{Title: "ABC"}]),但它似乎沒有綁定。我嘗試使用$.when().then()來代替(因爲我更喜歡它),但即使計算的值被延遲,它仍然不會更新。

對我來說真正複雜的部分是可變範圍。當涉及範圍時,模塊揭示模式很糟糕。我一直在爲這3個小時絞盡腦汁......如果任何人都可以引導我朝着正確的方向前進,那將是值得讚賞的。

編輯使用淘汰賽3.1(如果它幫助)

回答

6

read回調是完全錯誤的。

回調:

function (data) { 
    return data; 
} 

是死的代碼,它的返回數據給jQuery函數調用此回調,這是要幹什麼與它無關。

您需要返回延期本身:

read: function() { 
    return $.get("http://horodyski.me/api/skills"); 
} 

您還需要異步擴展這裏:http://smellegantcode.wordpress.com/2012/12/10/asynchronous-computed-observables-in-knockout-js/

ko.extenders.async = function(computedDeferred, initialValue) { 
    var plainObservable = ko.observable(initialValue), currentDeferred; 
    plainObservable.inProgress = ko.observable(false); 

    ko.computed(function() { 
     if (currentDeferred) { 
      currentDeferred.reject(); 
      currentDeferred = null; 
     } 

     var newDeferred = computedDeferred(); 
     if (newDeferred && (typeof newDeferred.done == "function")) { 
      plainObservable.inProgress(true); 
      currentDeferred = $.Deferred().done(function(data) { 
       plainObservable.inProgress(false); 
       plainObservable(data); 
      }); 
      newDeferred.done(currentDeferred.resolve); 
     } else { 
      plainObservable(newDeferred); 
     } 
    }); 

    return plainObservable; 
}; 

使用,如:

var skills = ko.computed(...).extend({ async: null }); 

如果你要掛鉤在傳遞給您的視圖之前將其轉換爲JSON:

var skillsJson = ko.computed(...).extend({ async: null }); 
var skills = ko.computed(function() { 
    return transformData(skillsJson()); 
}; 

或者:

var skills = ko.computed(function() { 
     return $.get("url").then(function (data) { 
      return transform(data); 
     }); 
    }); 
+1

如此接近。我想知道'async'是否是內置的擴展器。我無法在'ko.extenders'中找到它,並且在線文檔接近於零。這說...它仍然只是將承諾對象返回到'技能' – EHorodyski 2014-12-04 01:24:47

+0

啊,是的。道歉我已經有一個噩夢迴答這個問題......感謝您的耐心。將再次更新。 – 2014-12-04 01:31:05

+0

不用擔心,我非常感謝您的幫助。你會得到一個helluva'正確'檢查:-) – EHorodyski 2014-12-04 01:32:41