Ember.js在回调中返回计算属性

时间:2018-02-05 17:37:00

标签: ember.js callback handlebars.js computed-properties

我有一个计算属性,用于检查用户是否已经喜欢帖子:

  likeable: Ember.computed(function () {
    const currentUser = this.get('auth.credentials.id');
    const post = this.get('post.id');

    // Get likes and filter by post and current user

    this.get('store').query('like', {
      filter: {
         user_id: currentUser,
         post_id: post
       }
    }).then(function(like) {

      // Check if any likes were returned

      if (like.get('length') != 0) {
        console.log('length is not 0')
        return false
      } else if (like.get('length') === 0) {
        console.log('length is 0')
        return true
      }
    })
  })

在我的模板文件中调用它:

{{#if likeable}}
  <button class="like-button" {{action 'addLike' post}}>Like This Post</button>
{{/if}}

我能够看到console.logs,我知道正在检索正确的记录。但是,问题是likeable的值未更新,并且永远不会显示该按钮。我很确定这是因为我的条件是在一个回调中,而不是返回true到实际的计算属性。有没有解决的办法?

6 个答案:

答案 0 :(得分:1)

由于alizahid已经过了,你的计算属性没有返回值,你的内部承诺中的return语句只返回到promise链而且没有到达你的属性之外。

尝试使用return

返回您的媒体资源的承诺结果
  likeable: Ember.computed(function () {
    const currentUser = this.get('auth.credentials.id');
    const post = this.get('post.id');

    // Get likes and filter by post and current user

    return this.get('store').query('like', {
      filter: {
         user_id: currentUser,
         post_id: post
       }
    }).then(function(like) {

      // Check if any likes were returned

      if (like.get('length') != 0) {
        console.log('length is not 0')
        return false
      } else if (like.get('length') === 0) {
        console.log('length is 0')
        return true
      }
    })
  })

如果这没有用,你可能需要将promise链包装成DS.PromiseObject(参见docs),这就是ember-data处理promise返回模板的方式。

  likeable: Ember.computed(function () {
    const currentUser = this.get('auth.credentials.id');
    const post = this.get('post.id');

    // Get likes and filter by post and current user

    return DS.PromiseObject.create({
      promise: this.get('store').query('like', {
        filter: {
          user_id: currentUser,
          post_id: post
        }
      }).then(function (like) {

        // Check if any likes were returned

        if (like.get('length') != 0) {
          console.log('length is not 0')
          return false
        } else if (like.get('length') === 0) {
          console.log('length is 0')
          return true
        }
      })
    });
  })

答案 1 :(得分:0)

这个函数运行后你有没有尝试过console.logging?我想知道这是不是一个异步问题。在将like设置为true或false之后,可能必须再次获取帖子,或者将此逻辑移动到后端序列化程序并在那里设置likeable的值。

答案 2 :(得分:0)

第二个想法,我认为应该在你的Ember模型上定义void foo(char **str) { *str = "World"; } void bar(void) { const char *x = "Hello"; puts(x); // points to "Hello" foo(&x); puts(x); // points to "World" } 属性 https://guides.emberjs.com/v2.18.0/object-model/computed-properties-and-aggregate-data/

答案 3 :(得分:0)

你要回来的布尔无处可去。您需要返回要解析的布尔值的承诺。

你也可以尝试async版本,但我没有测试过它可能无效。

likeable: Ember.computed(async function() {
  const post_id = this.get('post.id')
  const user_id = this.get('auth.credentials.id')

  // get likes and filter by post and current user
  const like = await this.get('store').query('like', {
    filter: {
      post_id,
      user_id
    }
  })

  return like.get('length') === 0
})

答案 4 :(得分:0)

您不应该在计算属性中考虑异步行为,Ember通过运行循环管理所有计算,这意味着它不会等待计算来解析承诺。

处理此问题的方法是进行异步调用并设置属性具有副作用,可能是在ConstraintLayout挂钩期间:

didInsertElement

答案 5 :(得分:0)

正如其他答案所指出的那样,计算属性和承诺并不能很好地发挥作用。 https://emberigniter.com/guide-promises-computed-properties/ - 检查一下,这解释了如何很好地解决这个问题。基本上,要么使用并发任务,要么使用特殊的承诺支持对象。我每次都会同时执行任务!