Ember.js 在回调中返回计算 属性
Ember.js returning to computed property within a callback
我有一个计算 属性 检查用户是否已经喜欢 post:
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 到实际计算的 属性。有没有解决的办法?
这个功能有运行后,你试过console.logginglikeable吗?我想知道这是否是一个异步问题。在将 likeable 设置为 true 或 false 后,您可能需要再次获取 post,或者将此逻辑移至后端序列化程序并在那里设置 likeable 的值。
再三考虑,我认为 likeable
属性 应该在您的 Ember 模型上定义
https://guides.emberjs.com/v2.18.0/object-model/computed-properties-and-aggregate-data/
您return输入的布尔值无处可去。您需要 return 布尔值的承诺才能解析。
你也可以试试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
})
您不应该考虑计算属性中的异步行为,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);
});
},
});
正如其他答案所指出的那样,计算 属性 和 promises 不能很好地配合。 https://emberigniter.com/guide-promises-computed-properties/ - 看看这个,这很好地解释了如何去做。基本上,要么使用并发任务,要么使用特殊的承诺支持对象。我每次都去并发任务!
正如 alizahid 已经指出的那样,您计算的 属性 没有 return 值,您内部承诺中的 return 语句仅 return 到承诺链并且不要'到达你的 属性.
外面
尝试 return 您的 属性 与 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 处理承诺的方式 returns 到模板。
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
}
})
});
})
我有一个计算 属性 检查用户是否已经喜欢 post:
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 到实际计算的 属性。有没有解决的办法?
这个功能有运行后,你试过console.logginglikeable吗?我想知道这是否是一个异步问题。在将 likeable 设置为 true 或 false 后,您可能需要再次获取 post,或者将此逻辑移至后端序列化程序并在那里设置 likeable 的值。
再三考虑,我认为 likeable
属性 应该在您的 Ember 模型上定义
https://guides.emberjs.com/v2.18.0/object-model/computed-properties-and-aggregate-data/
您return输入的布尔值无处可去。您需要 return 布尔值的承诺才能解析。
你也可以试试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
})
您不应该考虑计算属性中的异步行为,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);
});
},
});
正如其他答案所指出的那样,计算 属性 和 promises 不能很好地配合。 https://emberigniter.com/guide-promises-computed-properties/ - 看看这个,这很好地解释了如何去做。基本上,要么使用并发任务,要么使用特殊的承诺支持对象。我每次都去并发任务!
正如 alizahid 已经指出的那样,您计算的 属性 没有 return 值,您内部承诺中的 return 语句仅 return 到承诺链并且不要'到达你的 属性.
外面尝试 return 您的 属性 与 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 处理承诺的方式 returns 到模板。
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
}
})
});
})