Ember.js 在回调中返回计算属性
Posted
技术标签:
【中文标题】Ember.js 在回调中返回计算属性【英文标题】:Ember.js returning to computed property within a callback 【发布时间】: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。有没有解决的办法?
【问题讨论】:
【参考方案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/ - 看看这个,这解释了如何很好地进行。基本上,要么使用并发任务,要么使用特殊的承诺支持对象。我每次都处理并发任务!
【讨论】:
以上是关于Ember.js 在回调中返回计算属性的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Ember.js 中创建计算属性以查看单个 Ember Data 属性是不是脏?
组件中的 Ember.js 计算属性 vs 观察者 vs didReceiveAttrs()