【问题标题】:Promise value not put into template after resolved解决后未放入模板的承诺值
【发布时间】:2014-02-01 10:17:30
【问题描述】:

我对 javascript 和 Promise 还很陌生,所以我可能没有掌握所有基本概念,但我正在尝试。

我的模型中有一个检查友谊状态的函数:

 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')

不,我只想通过以下方式在我的模板中输出这个值(例如 3):

FriendStatus :{{ friendShipStatus}}<br>

但我只得到对象输出:

朋友状态:[对象对象]

如果我通过 log helper {{ log friendShipStatus }} 记录输出,我看到 promise 用值 3 解析。为什么这个值没有放入我的模板中?

【问题讨论】:

  • 如果 - 您设置一个字符串值(在 RSVP 调用上方初始化)而不是返回 RSVP,然后在函数底部返回该空字符串并让数据绑定魔术改变它在他们回调期间?
  • 尝试用self.set('friendShipStatus', 3)替换return 3
  • 我现在用 self.set 完成了 ..... 将其发布为我可以接受的答案
  • 你绝对不想那样做……

标签: javascript ember.js handlebars.js


【解决方案1】:

下面有一种更高级的方法,但这种方法也很有效。

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

设置计算属性的值是一种反模式,计算属性应该就是这样,一个计算自身并返回结果的属性。如果你设置它,你将炸毁计算的属性并说这个属性的值是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}},它将代理到promise,因为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

【讨论】:

  • 我已经尝试过您的版本,但遇到了一些问题。我只尝试了您在下面描述的版本,但是我的friendShipStatus 仍然是“”。我与您的其他示例进行了比较,还添加了 on('init) 函数。但是在初始化时,即使在没有访问该函数的页面上,该函数也会被触发多次,并且在该函数的 15 次调用之一中,“用户”是未定义的,这会导致错误。
  • 我绝对不推荐使用这样的容器。如果你这样做了,你可以事先检查它是否为空,如果是则退出该方法。
  • 我还更新了一种更高级的方法,可以更好地满足您的需求(时间方面)
猜你喜欢
  • 1970-01-01
  • 2020-03-16
  • 2022-01-27
  • 1970-01-01
  • 2020-10-22
  • 2014-12-15
  • 2016-04-05
  • 2017-07-07
  • 1970-01-01
相关资源
最近更新 更多