0

我正在尝试将 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');
  }

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

最后,我最后一次尝试是使用@computed属性来weekPosts代替monthPosts,就像这样:

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

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

=> 但它总是返回 a Promise,所以我不能.reduce从 a 使用的计算属性调用它Component

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

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

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

谢谢 !

4

1 回答 1

1

观察者不适用于您想做的事情——因为看起来您想根据何时userId更改响应式地重新获取数据(使用 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;
  }

}

这里的优点是您还可以管理错误/加载/等状态。

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

在这种情况下,我们已经知道数据,userId我们想要派生查询,使用queryfrom ember-data-resources,也使用派生状态来提供以下 api

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

然后,它允许您定义get派生数据的其他术语weekPostsisLoading, 等。

派生状态比观察者代码更容易调试——而且它很懒,所以如果你不访问数据/getter/等,则不会计算该数据。

于 2022-02-21T00:58:06.017 回答