承诺在解决后未将值放入模板中

时间:2014-02-01 10:17:30

标签: javascript ember.js handlebars.js

我对javascript和promises相当新,所以我可能无法获得所有基本概念,但我正在尝试。

我的模型中有一个检查friendshiptstatus的函数:

 friendShipStatus: function() {
            var self = this;
            return Ember.RSVP.all([this.container.lookup('user:current'), 
                                   this.get('myFriends'), 
                                   this.get('friendsWithMe'), 
                                   this.get('friends')]).then(function(result){
                var user = result[0], myFriends = result[1],
                    friendsWithMe = result[2], friends = result[3] 
                if(friends.contains(user)){
                    return 2;
                } else if(friendsWithMe.contains(user)){
                    return 4;
                } else if(myFriends.contains(user)){
                    return 1;
                } else if (self.get('id') === user.get('id')){
                    return 3;
                } else {
                    return 0;
                }
            });

    }.property('friends')

不,我只想通过以下方式在我的tmeplate中输出此值(例如3):

FriendStatus :{{ friendShipStatus}}<br>

但我只得到对象输出:

  

FriendStatus:[object Object]

如果我通过日志帮助器{{ log friendShipStatus }}记录输出,我看到使用值3解析了promise。为什么这个值不会被放入我的模板中?

1 个答案:

答案 0 :(得分:8)

下面有一种更先进的方法,但这种方法也适用。

您将要使用观察者,然后将另一个属性设置为结果。导致promises的计算属性应该用作promises(在其他东西想要等到值可用的情况下)。

设置计算属性的值是反模式,计算属性应该只是一个计算自身并返回结果的属性。如果你设置它,你将爆破计算属性并说这个属性的值是x。这将破坏计算属性,之后不再更新。

http://emberjs.jsbin.com/OfOhuZub/1/edit

goodValue: '',

goodObserves: function(){
    var self = this,
        change = this.get('yourInput'),
        promise;

    promise = new Ember.RSVP.Promise(function(resolve){
      Em.run.later(function(){
        resolve(change);
      }, 200);
    });

    promise.then(function(result){
       self.set('goodValue', result);
    });

}.observes('yourInput').on('init'),

badComputed: function(){
    var self = this,
        change = this.get('yourInput'),
        promise;

    promise = new Ember.RSVP.Promise(function(resolve){
      Em.run.later(function(){
        resolve(change);
      }, 200);
    });

    promise.then(function(result){
       // AHHH, I'm overwriting my computed property, Whoops
       self.set('badComputed', result);
    });
}.property('yourInput')

在你的情况下,它会是这样的:

friendShipStatus: '',
friendShipStatusObserver: function() {
        var self = this;
        Ember.RSVP.all([this.container.lookup('user:current'), 
                               this.get('myFriends'), 
                               this.get('friendsWithMe'), 
                               this.get('friends')]).then(function(result){
            var user = result[0], myFriends = result[1],
                friendsWithMe = result[2], friends = result[3] 
            if(friends.contains(user)){
                self.set('friendShipStatus', 2);
            } else if(friendsWithMe.contains(user)){
                self.set('friendShipStatus', 4);
            } else if(myFriends.contains(user)){
                self.set('friendShipStatus', 1);
            } else if (self.get('id') === user.get('id')){
                self.set('friendShipStatus', 3);
            } else {
                self.set('friendShipStatus', 0);
            }
        });

}.observes('friends')

更高级的方法

您还可以构建一个promise代理对象,在您的情况下可以更轻松地工作。基本上你构建了一个ObjectProxy(这与ObjectController用于从模型到模板的代理属性的用法相同)。但是你添加了一个扭曲,你使用PromiseProxyMixin,这将允许您从承诺的解决方案代理值。你不能只使用结果{{goodComputed}},这只会打印出promise代理。因此,您需要将已解析的值包装在某种对象resolve({value: change})中。进入对象后,您可以在模板中使用{{goodComputed.value}},它将代理到承诺,因为ObjectProxy上不存在值。我在下面列举了一个例子。

  goodComputed: function(){
    var self = this,
        change = this.get('yourInput'),
        promise,
        result;
    promise = new Ember.RSVP.Promise(function(resolve){
      Em.run.later(function(){
        resolve({value:change});
      }, 200);
    });

    result = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin).create({
      promise: promise
    });

    return result;
  }.property('yourInput'),

http://emberjs.jsbin.com/OfOhuZub/2/edit