在emberjs中从组件类调用API调用是一个好方法吗?

Imi*_*mit 1 ember.js

我现在正在学习 emberjs,我想知道这是否是在组件类的函数内发出获取请求(例如按钮单击)并将数据存储在类组件中的常见方法。例如:

export default class ExampleComponent extends Component {
  @tracked items;
  @action async toggleCall() {
    await fetch(...)
    .then(...)
  }
}
Run Code Online (Sandbox Code Playgroud)

或者你在 emberjs 中以不同的方式做到这一点?

Nul*_*uli 5

是的,这是一个完全合理的方法。

但是,您需要以某种方式手动调用toggleCall

我最喜欢的在组件中加载内容或执行任何异步操作的方法是使用“资源”通过派生数据延迟且反应性地执行此操作。

有一个实用程序trackedFunction从以下位置调用: https: //github.com/nullvoxpopuli/ember-resources 具体文档在这里

您的示例可以重写为:

import Component from '@glimmer/component';
import { trackedFunction } from 'ember-resources';

export default class Example extends Component {
  fetchItems = trackedFunction(this, async () => {
    let response = await fetch( /* ... */);
    return await response.json();
  });

  get items() {
    // specify a default value of empty array when value is undefined
    // (value is undefined before the function finishes running)
    return this.fetchItems.value ?? [];
  }
}
Run Code Online (Sandbox Code Playgroud)

主要区别:

  • 访问时将trackedFunction自动调用
  • 重复访问不会重新调用该函数
  • 在 之前使用的任何@tracked数据await都会trackedFunction“纠缠”,因此对该@tracked数据的更改将导致该函数再次运行,例如,如果您有一个查询参数
  @tracked filter = 'name:starts_with=a';

  fetchItems = trackedFunction(this, async () => {
    let url = `...?${this.filter}`;
    let response = await fetch(url /* ... */);
    return await response.json();
  });
Run Code Online (Sandbox Code Playgroud)

fetchItems是反应性的,因为现在发生filter变化时,fetchItems将重新调用自身。


但是,如果您打算保留点击请求行为(这很常见!),您可能会对 ember-concurrency 感兴趣,它提供了一些很好的人体工程学实用程序,用于处理/保护您的数据免遭使用人机的愚蠢行为-交互——例如用户单击按钮后不重新请求,并在请求完成之前再次单击该按钮。

那么你的例子将是:

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { dropTask } from 'ember-concurrency';

export default class Example extends Component {
  @dropTask
  *fetchItems() {
    let response = await fetch( /* ... */);
    return await response.json();
  }

  get items() {
    return this.fetchItems.lastSuccessful.value ?? [];
  }

  // click handler can be called any number of times,
  // which would, in turn, call fetchItems any number of times,
  // but only one `fetch` request will ever run at a given time.
  @action
  handleClick() {
    this.fetchItems.perform();
  }
}

Run Code Online (Sandbox Code Playgroud)

有关 ember-concurrency 的文档:https: //ember-concurrency.com/

  • 好的!非常感谢您这么详细的回答!:) (2认同)