添加加载指示每当应用程序停滞

Add loading indicator whenever app stalls

本文关键字:应用程序 停滞 加载 指示 添加      更新时间:2023-09-26

我有一个动作,导致应用程序挂起几秒钟。我想添加一些加载指示器来显示它在做一些事情,而不是冻结。

我已经尝试了一些东西,其中一些是完整的实验,我认为不会起作用。

首先,这是我在尝试添加任何类型的指示符之前的内容:

filterObserver: function(){
  // we needed the debounce because it would crash the app if it took too long
  // it has to filter through ~10,000 records
  Ember.run.debounce(this, this.filterFoo, 1500); 
}.observes('filterValue'),

我认为这将工作,但它似乎等待,直到一切在观察者完成之前,它渲染页面:

controller.js

isLoading: false,
filterObserver: function(){
  this.set('isLoading', true);
  Ember.run.debounce(this, this.filterFoo, 1500);
  this.set('isLoading', false);
}.observes('filterValue'),

template.hbs

<ul class="project-list {{if isLoading 'loading'}}">
{{#each group in foo}}
  {{group-item group=group}}
{{/each}}
</ul>

所以,我想也许我需要强制它进行渲染以显示更改。我将整个列表移动到组件中,以便访问组件的rerender方法:

component.js

export default Ember.Component.extend({
  loadingObserver: function() {
    this.rerender();
    Ember.run.schedule('afterRender', this, function() {
      this.sendAction('filterAll');
    });
  }.observes('isLoading')
});

controller.js

actions: {
  filterAll: function() {
    Ember.run.debounce(this, this.filterActivities, 1500);
    this.set('isLoading', false);
  }
}

所以,我想也许Ember的运行循环会起作用。这时,我非常沮丧,但我想尝试所有可能有效的方法:

component.js

export default Ember.Component.extend({
  loadingObserver: function() {
    this.rerender();
    Ember.run.schedule('afterRender', this, function() {
      this.sendAction('filterAll');
    });
  }.observes('isLoading')
});

这些都不起作用。

我知道afterModel, destroy等不同的路由方法。此时我的页面已经加载完毕,所以在本例中这些都不起作用。

我相信这是因为Ember会等到观察者中的一切都完成后才渲染模板。因此,我需要一些方法,以便它在模板中任何更改时都显示此指示器,或者等待它完成设置变量并添加类,然后再继续执行操作的代码。

想法吗?想法吗?

为了记录,我知道1.13引入了微光,这将有助于应用程序挂起。然而,我们依赖于几个仍然使用1.11的插件,所以我担心我们暂时无法摆脱它。

编辑

显然run.later只适用于我的情况,因为我也使用run.debounce。下面的代码在我的特殊情况下不起作用,因为run.next认为run.debounce代码已经完成,而实际上并没有。这应该在大多数情况下工作:

Ember.run.once(this, function() {
  this.set('isLoading', true);
});
Ember.run.next(this, function() {
  // your code here
  // `isLoading` will be true while this is running,
  // so your loading indicator will still be present
  this.set('isLoading', false);
});

如果你需要一个在Ember的运行循环之外运行的指示器,我的原始答案仍然有效。但是,您可能在绝大多数情况下都能够使用上面的代码。


原始回答

我实际上能够解决这个问题。我只是使用Ember.run.later,以便让Ember等到所有其他异步事件结束。在我的应用程序中,这相当于:

var _this = this;
this.set('isLoading', true);
Ember.run.debounce(this, this.filterFoo, 1500);
Ember.run.later(function() {
  _this.set('isLoading', false);
}, 1500); // I set the timeout to 1500 ms because that's the same as the debounce

我在烬的指南中发现了这个:异步动作的旋转按钮。你可以在Ember的文档中阅读更多关于run.later的信息。

如果我不这样做,它会尝试一次执行所有的代码。这基本上只是让它等待,直到它完成或超时。