在 Ember 车把模板中呈现已解决的承诺值

Posted

技术标签:

【中文标题】在 Ember 车把模板中呈现已解决的承诺值【英文标题】:Rendering resolved promise value in Ember handlebars template 【发布时间】:2014-01-04 13:24:06 【问题描述】:

有没有一种在把手模板中呈现承诺结果的好方法?

例如,我有以下模型:

App.TopicItem = DS.Model.extend(
  topic: DS.belongsTo('topic'),
  paddedPosition: function() 
    return this.get('topic.course.lessons').
      then(function(lessons) 
        return lessons.indexOf(topicItem);
      ).
      then(function(index)
        var position  = index;

        if (position < 0)  
          return;
        

        position = position + 1;

        return (position < 10 ? $.rjust(position, 2, '0') : position.toString());
      );
  .property('topic.course.lessons')
);

我想像这样在车把模板中渲染位置值:

topicItem.paddedPosition

有没有什么好的方法可以做到这一点?

【问题讨论】:

看起来您需要等待 paddedPosition 返回,类似于 topicItem.get('paddedPosition').then(function() Handlebars.compile();); 不确定 ember,但这是一般方法 :) 不确定是否等待 paddedPosition 就像试图弄清楚 Ember.Handlebars 是否自动解析承诺一样。 【参考方案1】:

这似乎是一个意外的行为。 有一个 bug 解决了这个问题:https://github.com/emberjs/ember.js/issues/11046

【讨论】:

今天在该问题上添加了我的 +1 后,它被关闭并解释说它不是但是,而是一个尚不存在的功能。他们确实有计划在核心解决这个问题,并且建议/请求为 RFC 做出贡献。【参考方案2】:

您可以让属性延迟设置,例如:

App.TopicItem = DS.Model.extend(
  topic: DS.belongsTo('topic'),
  paddedPosition: function(key, value) 
    if (arguments.length > 1) 
      // > 1 args = this is a `set`
      return value;
     else 
      // otherwise this is a `get`
      var _this = this;
      value = null;

      this.get('topic.course.lessons').
        then(function(lessons) 
          // do stuff based on result
          var padded = ...;
          // when the promise is resolved, set this property with the value
          _this.set("paddedPosition", padded);

          // if the promise resolves immediately, set `value` so we return
          // the calculated value and not null
          value = padded;
        );

      // returns null if the promise doesn't resolve immediately, or 
      // the calculated value if it's ready
      return value;
    
  .property('topic.course.lessons')
);

当它第一次被访问时,它会开始计算,就像任何时候课程发生变化一样,一旦完成,它就会将自己设置为计算的结果。

这是有效的,因为在 get 和 set 上都调用了计算属性,您可以通过参数的数量来区分两者 - 1 表示 get,大于 1 表示 set(它曾经是 2,现在你得到 3 所以最好的检测方法是 > 1)。更多关于 in the docs.

从计算属性(在 get 或 set 中)返回的任何内容都会被缓存,直到其依赖属性发生更改 - 在本例中为 topic.course.lessons

在上面的例子中,当第一个get 进来时,我们开始计算并返回null。这现在被缓存为属性的值,如果在 promise 解决之前有任何其他调用此属性,那么它将返回 null

一旦 Promise 解决,我们就使用计算值调用同一属性上的 set。我们只是在 setter 中返回它,它现在被缓存为属性的值。

直到从属属性发生变化 (topic.course.lessons),或者新值为 set,然后从属性返回缓存值。

【讨论】:

这很有趣,完全适合我。我试图理解 - 它是如何工作的? :) @alvincrespo 我已经用更多解释更新了答案 - 希望这是有道理的。 非常感谢您的解释。我们今天对此进行了一些测试,发现在车把中使用这种方法存在间歇性问题。出于某种奇怪的原因,即使 promise 解析并设置了值,模板仍然会选择 null。 如果承诺立即解决,那么它会尝试设置属性,但无论如何它都会返回 null。我会用一个可能的解决方案来编辑​​答案! @alvincrespo 之所以有效,是因为每个模型实例都是模型的一个新实例。

以上是关于在 Ember 车把模板中呈现已解决的承诺值的主要内容,如果未能解决你的问题,请参考以下文章

Ember:访问模板中的侧载模型关系数据

解决承诺不显示模板中的数据

将普通页面 css 与 ember 车把 css 混合

如何在车把 ember 中定义自定义助手

无法将车把数据导入模板

如何传递任意数据以在 Ember 模板中呈现?