2014-12-03 71 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