EmberJS Octane 观察器的语法无效

Invalid syntax on EmberJS Octane observers

我正在尝试将 Ember 观察器与 EmberJS Octane 最新版本 (4.1.0) 一起使用,但它似乎不起作用。

这是我想要实现的目标:

export default class SummaryService extends Service {
  @service store;
  @service authentication;

  @reads('authentication.userId') userId;

  @tracked weekPosts;
  @tracked monthPosts;

  @observer('userId')
  loadPosts() {
    this._loadPosts(this.userId);
  }

  _loadPosts(userId) {
    this.store.query('posts', { filter: { 'current-week': 1, 'user-id': userId } })
      .then((posts) => {
        this.set('weekPosts', posts);
      });
    this.store.query('posts', { filter: { 'current-month': 1, 'user-id': userId } })
      .then((posts) => {
        this.set('monthPosts', posts);
      });
  }
}

=> 语法无效。

我也试过了:

@observer('userId', function() {
  this._loadPosts();
});

=>确实调用了观察者,但是this未定义。

我也试过了:

  init() {
    super.init(...arguments);
    this.addObserver('currentUserId', this, '_loadPosts');
  }

=> 但是这个不调用任何方法(即使使用内联方法定义)。

最后,我最后一次尝试是对 weekPostsmonthPosts 使用 @computed 属性,像这样:

export default class SummaryService extends Service {
  /* ... */

  @computed('userId')
  get weekPosts() {
    return this.store.query('posts', { filter: { 'current-week': 1 } })
      .then((posts) => { return posts; });
  }
}

=> 但它总是 returns 一个 Promise,所以我不能从一个 [=21= 使用的计算 属性 调用 .reduce ] :

export default class SummaryComponent extends Component {
  @computed('weekPosts')
  get weekPostsViewsCount() {
    return this.weekPosts.reduce((sum, post) => { return sum + post.viewCount });
  }
}

我终于用 weekPosts 计算的 属性 返回的 ArrayProxy.extend(PromiseProxyMixin) 得到了一些非常丑陋的东西,但我绝对不满意,原因如下:

  1. 如此简单的事情需要这么多代码
  2. 使用 weekPosts 的一切(组件、模板)都必须确保在使用它之前履行承诺
  3. 承诺是服务的实现细节,不应该以任何方式可见

谢谢!

Observers 不会为你想做的事工作——因为看起来你想根据 userId 的变化反应性地 re-fetch 数据(使用 ember-data),我有一个图书馆建议:

有了这个库,我们可以用这个替换你的大部分服务:

import { query } from 'ember-data-resources';

export default class SummaryService extends Service {
  @service authentication;

  @reads('authentication.userId') userId;

  _weekPosts = query(this, 'posts', () => ({
    filter: { 'current-week': 1, 'user-id': this.userId 
  }));

  _monthPosts = query(this, 'posts', () => ({
    filter: { 'current-month': 1, 'user-id': this.userId 
  }));

  get weekPosts() {
    return this._weekPosts.records ?? [];
  }

  get monthPosts() {
    return this._monthPosts.records ?? [];
  }

  get isLoading() {
    return this._weekPosts.isLoading || this._monthPosts.isLoading;
  }

}

这里的优势是您还可以管理 error/loading/etc 个状态。

这使用了一种称为“派生状态”的技术/模式,而不是执行操作、对更改做出反应或与生命周期交互,而是定义数据的派生方式来自其他数据。

在这种情况下,我们有已知数据 userId,我们希望使用 ember-data 中的 query 派生 查询-资源,也使用派生状态提供 the following api:

  • this._weekPosts
    • .records
    • .error
    • .isLoading
    • .isSuccess
    • .isError
    • .hasRun

然后允许您定义其他 get 派生数据的对象,weekPostsisLoading

派生状态比观察者代码更容易调试 -- 它是惰性的,因此如果您不访问 data/getters/etc,则不会计算该数据。