ember.js - 关于 Ember 中异步的一些问题
问题描述
我在一段时间内使用 emberjs,现在我想完善我对 ember 本质的理解。
问题 1.model()
路由的钩子是编写异步代码(获取所有需要的数据)的最佳位置,
我说得对吗?我是否应该尝试将所有网络请求(或至少大部分)放在路由模型中?
问题 2. 组件钩子具有同步性。这是否意味着在钩子中编写异步代码是一个错误的决定?
比如说,我有一个异步init()
钩子来计算一些数据,并didRender()
在我希望使用这些数据的地方钩子。当 ember 调用init()
时,它返回一个 Promise,因此它从堆栈移动到一个特殊的队列,并且 ember 不会等到事件循环将该代码返回到堆栈。所以 ember 会运行下一个钩子,而当didRender()
被执行时,init()
钩子可能没有完成,预期的数据可能不存在。那正确吗?
问题 3. 服务挂钩也应该是同步的。因为当服务被注入到组件中并被使用时,ember 也不会等到异步钩子完成。
比如说,我有一个带有products
属性的购物车服务。产品 ID 存储在本地存储中,我想从服务器获取这些产品以将它们设置为products
属性。
import Service from '@ember/service';
import { A } from '@ember/array';
import { inject as service } from '@ember/service';
export default Service.extend({
store: service(),
init(...args) {
this._super(args);
this.set('products', A());
},
async loadProducts() {
const cartProducts = A();
const savedCartProducts = localStorage.getItem('cartProducts');
if (savedCartProducts) {
const parsedSavedCartProducts = JSON.parse(savedCartProducts);
const ids = Object.keys(parsedSavedCartProducts);
if (ids.length > 0) {
const products = await this.store.query('product', {id: Object.keys(parsedSavedCartProducts)});
products.forEach(p => {
p.set('cartQuantity', Number(parsedSavedCartProducts[p.id].qty));
cartProducts.pushObject(p);
});
}
}
this.products.pushObjects(cartProducts);
},
...
});
例如,如果我loadProducts()
从服务中调用,init()
我将无法使用this.cart.products
in controllers/application.js
。因为服务已经准备好了,但是异步init()
还在执行。那么,我应该在routes/application.js
model()
挂钩中调用它吗?
问题 4. 如果有一些通用组件不引用任何路由,但该组件需要来自服务器的一些数据,我应该在哪里发出异步请求?还是计算属性和观察者是唯一的解决方案?
非常感谢。
解决方案
好问题在这里,你在正确的轨道上!
问题 1:是的,一般的经验法则是,在您熟悉事物之前,在路由钩子( 和 )中进行异步工作beforeModel
可以model
更afterModel
容易地思考正在发生的事情。最终,您可能希望开始调整默认值以适应您的自定义 UI 需求,但从这条规则开始是最简单的
问题 2-4:你在这里问了几个关于异步代码的问题,所以在这里更广泛地回答。
首先,服务可以异步或不异步,但除非您从钩子(如路由钩子)调用这些方法,否则您负责处理异步结果。例如,Ember 数据存储是一个异步返回数据的服务
但是,如果您遇到确实需要在组件中执行异步的情况,推荐的帮助解决此问题的插件是 Ember Concurrency:http ://ember-concurrency.com/docs/introduction/
Ember Concurrency 有助于解决您尚未遇到的许多异步错误和边缘情况,但如果您开始在组件中编写异步代码,它们将会解决。因此,我强烈建议您了解更多有关它的信息。
祝你好运!
推荐阅读
- python - 如何在 HTML 输入表单中保持文本格式?
- python - 使用训练有素的神经网络,图像显示更广泛的周围环境
- javascript - 使用虚拟列表和不同大小的项目拖放
- android - 如何从服务记录 Gboard 在其他应用程序中的输入
- javascript - Flask 应用程序未在 html 中返回 javascript 内容
- c# - 将数据库表插入另一个数据库表特定的列?WPF
- javascript - 如何在 Django 模板上传递 Python 列表并在 JavaScript 中使用它?
- excel - 如何使用 VBA 宏更新存储在客户 SharePoint 上的多个 excel (.xlsx) 文件
- laravel - 如何在 Laravel Nova 工具中使用 React?
- javascript - 反应上传多个文件