How to delay computed properties to recomputed the

2020-07-17 05:10发布

This question is come up with Component Example from the homepage of Ember.js, here's the code:

App.GravatarImageComponent = Ember.Component.extend({
  size: 200,
  email: '',

  gravatarUrl: function() {
    var email = this.get('email'),
        size = this.get('size');

    return 'http://www.gravatar.com/avatar/' + hex_md5(email) + '?s=' + size;
  }.property('email', 'size')
});

When I try this example I noticed that everytime I input a character the browser will fire a request to get the avatar. If my email address have 30 characters, there will be 30 times requests got fired until the right one was returned from the server. I think this is too inefficient, isn't it?

After digging out the guides, I didn't find there is a way to solve this problem, so I was wondering: is this possible to delay re-compute a computed property for, say, like 1000ms? or is there a better way to deal with this type of scenario?

2条回答
家丑人穷心不美
2楼-- · 2020-07-17 05:43

You can debounce it, which gives you a similar feeling of it reacting without having to do anything other than typing:

App.GravatarImageComponent = Ember.Component.extend({
  size: 200,
  email: '',
  fetchEmail:'',

  watchEmail: function(){
    Em.run.debounce(this, this.setEmail, 400)
  }.observes('email'),

  setEmail: function(){
    this.set('fetchEmail', this.get('email'));
  },

  gravatarUrl: function() {
    var email = this.get('fetchEmail'),
        size = this.get('size');

    return 'http://www.gravatar.com/avatar/' + md5(email) + '?s=' + size;
  }.property('fetchEmail', 'size')
});

Example: http://emberjs.jsbin.com/lacefi/1/edit

查看更多
兄弟一词,经得起流年.
3楼-- · 2020-07-17 05:48

I had to put a debouncer on my observer to limit execution of my actual business logic in one of my project.

In this case, you can change your computed property gravatarUrl to normal property and move logic to build url on a observer, which observes email and size and update gravatarUrl, and then simply put a debouncer on your observer. I haven’t tested below code but here is the idea:

App.GravatarImageComponent = Ember.Component.extend({
  size: 200,
  email: '',

  gravatarUrl: '',

  gravObserver: function() {
    Ember.run.debounce(this, this.updateGravUrl, 1000);

  }.observes('email', 'size'),

  updateGravUrl: function(){
    var email = this.get('email'),
        size = this.get('size');

  this.set('gravatarUrl','http://www.gravatar.com/avatar/' + hex_md5(email) + '?s=' + size);
  }
});
查看更多
登录 后发表回答