异步函数作为敲除绑定目标

时间:2013-09-05 08:32:30

标签: javascript data-binding asynchronous knockout.js

我在这里有一个场景我需要使用属性绑定(attr)但是要应用的实际值是通过回调返回的,所以有没有办法让knockout以某种方式变成回调?

我认为答案是否定的,我将需要使用其中一个异步淘汰插件,但由于其中一些需要脏标等设置,我宁愿不要用我的模型复杂化。

所以这是一个代码示例:

function SomeViewModel()
{
    var someStorageMechanism = new StorageMechanism();

    this.GetUserPicture = function(userId) {
        someStorageMechanism.GetUserData(userId, function(userData) {
            // should really be using a callback argument then do callback(userData.picture); but knockout has no notion of this
        });
    };
}

<img data-bind="attr: { src: GetUserPicture($data.userId) }"/>

在上面的例子中,GetUserPicture理想情况下应该返回一个图像数据字符串或一个url,但是在这种情况下需要从一个异步工作的底层对象中检索数据,所以有什么简单的方法可以解决这个问题?

1 个答案:

答案 0 :(得分:2)

"is there any way to get knockout to somehow become callback aware?"

是的,您可以使用订阅。所有observable,observableArrays和computed都继承自subscribable类型,因此您可以这样做:

var foo = ko.observable("foo");
foo.subscribe(function (newValue) {
  // When foo updates, this function is called
});

使用订阅,您甚至可以设置临时订阅,如果您不再需要它们,也可以在以后取消订阅。

var fooSub = foo.subscribe(function (newValue) {
  // When foo updates, this function is called
});
// Somewhere else in the app...
fooSub.dispose();

默认情况下,订阅会订阅名为“更改”的主题。这意味着当observable的值发生更改时,它会调用具有newValue的任何订阅者(因此调用参数的名称),但您也可以设置订阅主题'beforeChange'的订阅,以便在某些值之前执行逻辑变化。

foo.subscribe(function (oldValue) {
  // Do logic on the oldValue here
}, null, 'beforeChange');

你可以在淘汰赛documentation中读到这个。但是,如果需要,您还可以订阅自定义主题。默认情况下,当observables的值发生更改时,'beforeChange'和'change'主题会在值更改之前和之后(分别)触发。但您可以订阅以后可以手动触发的自定义主题,以通知任何收听该主题的订阅者。

foo.subscribe(function (value) {
  // Do logic when observable notifies subscribers to the 'customTopic' topic
}, null, 'customTopic');

// Somewhere else in the app...
var value = "bar";
foo(value);
foo.notifySubscribers(value, 'customTopic');

通过这种方式,您可以在不直接引用彼此的单独视图模型之间设置通信。这是我对如何做到这一点的粗略理解,您可以通过观看Ryan Niemeyer的提示和技巧来了解更多信息video。特别是订阅部分。

通过这种方式,您可以在淘汰赛中执行一种回调。另请查看Ryan的Knockout-postbox库,该库扩展了observables以订阅并发布这些主题。


您还可以查看jQuery $.Deferreds,这是$ .ajax请求使用的基础部分。这不是淘汰赛的回调,但它是一种回调。

请告诉我这是否更符合您的需求。