【问题标题】:Ember.js returning to computed property within a callbackEmber.js 在回调中返回计算属性
【发布时间】:2018-07-15 15:34:05
【问题描述】:

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

  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。有没有解决的办法?

【问题讨论】:

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


    【解决方案1】:

    正如 alizahid 已经指出的那样,您的计算属性没有返回值,您内部 Promise 中的 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
          }
        })
      })
    

    如果这没有帮助,您可能必须将承诺链包装到 DS.PromiseObject(参见 docs)中,这就是 ember-data 处理承诺返回到模板的方式。

      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
            }
          })
        });
      })
    

    【讨论】:

      【解决方案2】:

      再想一想,我认为应该在您的 Ember 模型上定义 likeable 属性 https://guides.emberjs.com/v2.18.0/object-model/computed-properties-and-aggregate-data/

      【讨论】:

      • console.log('type is ', typeof like.get('length')) return 'type is number' using else 返回与之前相同的结果
      • 这个方法的问题是在函数返回likeableValue之后总是返回false。我很确定这是因为检查喜欢的函数是异步的。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        您返回的布尔值无处可去。您需要返回要解析的布尔值的 Promise。

        你也可以试试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
        })
        

        【讨论】:

          【解决方案5】:

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

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

          import Component from '@ember/component';
          export default Component.extend({
              didInsertElement() {
                  this._super(...arguments);
                  this.fetchLikesFromServer().then(like => {
                      this.set('likeable', like.get('length') === 0);
                  });
              },
          });
          

          【讨论】:

            【解决方案6】:

            正如其他答案所指出的,计算属性和承诺不能很好地配合。 https://emberigniter.com/guide-promises-computed-properties/ - 看看这个,这解释了如何很好地进行。基本上,要么使用并发任务,要么使用特殊的承诺支持对象。我每次都处理并发任务!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-02-14
              • 2013-06-29
              • 2013-04-25
              • 2018-02-03
              • 2018-10-13
              • 2021-02-16
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多