Ember.js 开发:认证、运行循环与性能优化
1. 蒙特里克(Montric)初始化与用户认证
在 Ember.js 应用中,蒙特里克(Montric)的初始化与用户认证是重要的环节。可以通过以下代码来处理用户认证信息:
if (data["user"] && data["user"].userRole != null) {
var cookieUser = Montric.User.create();
cookieUser.setProperties(data["user"]);
Montric.set('cookieUser', cookieUser);
} else {
Montric.set('cookieUser', null);
}
Montric.advanceReadiness();
上述代码的逻辑如下:
- 若 data["user"] 存在且 userRole 不为空,创建一个新的 Montric.User 对象,并将从服务器接收到的用户属性设置到该对象上,然后将其设置为 cookieUser 。
- 若不满足上述条件,则将 cookieUser 设置为 null 。
- 最后调用 Montric.advanceReadiness() 推进蒙特里克的初始化。
可以通过调用 Montric.deferReadiness() 暂停蒙特里克的初始化,这会告知 Ember.js 等待,直到调用 Montric.advanceReadiness() 才初始化控制器和路由器。这样做可以在这个时间段内获取应用所需的数据,比如认证用户信息,或者获取用于优化应用的数据。
具体操作步骤如下:
1. 调用 Montric.deferReadiness() 暂停初始化。
2. 向 /user 发送 XHR 请求以获取当前用户信息。
3. 根据服务器响应,若返回的用户对象包含 userRole ,则创建新的 Montric.User 对象并设置属性,然后调用 Montric.set('cookieUser', cookieUser) 。
4. 调用 Montric.advanceReadiness() 继续初始化。
2. Ember.js 应用的认证与授权
在 Ember.js 应用中,有两种实现认证和授权的方式,这里主要介绍使用 Mozilla Persona 这一第三方认证系统。
使用 Mozilla Persona 有诸多优势:
- 应用无需负责存储用户名和密码,避免了安全存储、密码哈希等问题,也无需担心用户信息被黑客窃取。
- 免费获得账户创建、编辑以及处理丢失和遗忘密码等功能。
- Persona 不依赖社交网络或其他应用平台,用户无需担心个人信息泄露,它只会向网站透露用户的电子邮件地址。
不过,即使 Mozilla Persona 是一个安全的认证提供者,所有认证提供者都存在安全漏洞,需要遵循 Mozilla Identity Team 制定的指南:
- 阅读最佳实践文档(https://developer.mozilla.org/en-US/Persona/Security_Considerations)。
- 阅读实施者指南(https://developer.mozilla.org/en-US/Persona/The_implementor_s_guide)。
3. Ember.js 运行循环:Backburner.js
Ember.js 的运行循环是其独特的概念,与 AngularJS 或 Backbone.js 等类似框架有所区别。运行循环并非连续执行的循环,在 Ember.js 的最终候选版本中,运行循环被提取到一个名为 Backburner.js 的微库中。虽然 Ember.js 内部使用 Backburner.js,但 Ember.js 内部的 API,包括运行循环 API 并未改变。
运行循环的主要作用是在应用中对事件、键值通知和定时器进行分组、协调和执行。它处于休眠状态,直到应用中发生有效事件或通过 API 手动启动。
为了更好地理解运行循环,以 Ember.js 版本的 TodoMVC 应用为例。该应用具有以下特性:
- 输入字段:用户可在应用顶部的文本字段中输入新的待办事项。
- 待办事项列表:用户添加至少一项后,事项会显示在文本输入字段下方的列表中。
- 标记任务为已完成复选框:待办事项列表中每个项目的左侧有一个复选框,用户可将该项目标记为已完成。
- 标记所有任务为已完成复选框:文本输入字段左侧的复选框,可让用户将所有剩余任务标记为已完成。
- 状态标签:屏幕左下角的标签显示尚未完成的任务数量。
假设用户添加了 100 项待办事项,之后想将所有任务标记为已完成。若用户点击“标记所有任务为已完成”复选框,若应用为每个任务单独更新 DOM,这将是非常耗时、缓慢且成本高昂的操作。此时,Ember.js 的运行循环就会发挥作用,帮助应用合理安排事件顺序,高效执行。
运行循环由一组预定义的队列组成,这些队列按数组顺序执行。默认情况下,Ember.js 包含五个队列:
| 队列名称 | 说明 |
| ---- | ---- |
| Sync | 包含所有涉及传播绑定数据的操作 |
| Actions | 默认队列,包含在所有绑定传播完成后、视图渲染到 DOM 之前需要执行的事件 |
| Render | 包含与视图渲染到 DOM 相关的事件 |
| AfterRender | 包含在标准渲染事件完成后需要执行的视图相关事件 |
| Destroy | 包含需要销毁的对象的事件 |
下面是运行循环的工作流程 mermaid 流程图:
graph LR
A[触发运行循环] --> B[Sync 队列]
B --> C[Actions 队列]
C --> D[Render 队列]
D --> E[AfterRender 队列]
E --> F[Destroy 队列]
F --> G[运行循环结束]
B -.-> B1(可能添加新事件到其他队列)
C -.-> C1(可能添加新事件到其他队列)
D -.-> D1(可能添加新事件到其他队列)
E -.-> E1(可能添加新事件到其他队列)
当用户点击“标记所有任务为已完成”复选框时,会触发一个新的运行循环,从 Sync 队列开始工作。此时 Sync 队列中至少有 400 个事件:
- 100 个事件用于更新待办事项列表中的每个任务,将 isCompleted 属性设置为 true 。
- 100 个事件是待办事项列表中每个复选框的绑定事件,其 checked 属性与待办事项的 isCompleted 属性绑定。
- 100 个事件是底部状态标签的更新事件,该标签与 TodosController 的 remainingFormatted 计算属性绑定,而该属性又与每个待办事项的 isCompleted 属性绑定。
- 100 个事件是顶部“标记所有为已完成”复选框的切换事件。
运行循环会确保当前队列以及之前的队列完全清空后,才会移动到下一个队列。例如,Sync 队列处理完成后,会将事件添加到 Render 队列,告知 Ember.js 重新绘制所有 101 个复选框,并将已完成的任务划掉,同时更新左下角的计数器。
综上所述,Ember.js 的运行循环机制有助于保持应用的响应性,确保数据绑定始终保持最新状态,同时通过合理安排事件顺序,减少 DOM 操作次数,提高应用性能。
Ember.js 开发:认证、运行循环与性能优化
4. 运行循环各队列详细分析
- Sync 队列 :Sync 队列是运行循环开始工作的第一个队列,它主要负责处理所有涉及传播绑定数据的操作。在 TodoMVC 应用中,当用户点击“标记所有任务为已完成”复选框时,Sync 队列会收到一系列与数据绑定相关的事件。这些事件包括更新每个任务的
isCompleted属性、处理复选框的绑定以及状态标签的更新等。Sync 队列的处理确保了数据的一致性和准确性,为后续的操作奠定了基础。 - Actions 队列 :Actions 队列是默认队列,包含在所有绑定传播完成后、视图渲染到 DOM 之前需要执行的事件。在 Ember.js 应用中,只有应用初始化和 RSVP 事件会被指定进入这个队列。RSVP 是 Ember.js 内部用于处理承诺(promises)的库。Actions 队列的存在保证了在数据绑定完成后,一些必要的操作能够在视图渲染之前执行,避免了不必要的冲突和错误。
- Render 队列 :Render 队列包含与视图渲染到 DOM 相关的事件。由于与浏览器的 DOM 树进行交互和操作是 Ember.js 执行的最耗时的任务之一,因此 Render 队列在 Sync 和 Actions 队列之后执行非常重要。这样可以确保在进行 DOM 操作之前,所有的数据绑定都已经完成,从而减少 DOM 操作的次数,提高应用的性能。在 TodoMVC 应用中,Render 队列会处理重新绘制复选框、划掉已完成任务以及更新计数器等操作。
- AfterRender 队列 :AfterRender 队列包含在标准渲染事件完成后需要执行的视图相关事件。有些视图可能需要访问渲染后的 DOM 元素,这些操作就需要在 AfterRender 队列中执行。例如,一个视图需要在渲染完成后追加或修改 HTML 元素的内容,就可以将相关事件添加到 AfterRender 队列中。AfterRender 队列的存在使得开发者可以在视图渲染完成后进行一些额外的操作,而不会影响到正常的渲染流程。
- Destroy 队列 :Destroy 队列包含需要销毁的对象的事件。通常,当用户在应用中从一个路由导航到另一个路由,或者状态发生变化导致不同部分的模板被渲染到 DOM 时,那些已经从 DOM 中移除且不再需要的视图会被添加到 Destroy 队列中。Destroy 队列的作用是确保这些不再使用的对象能够被及时销毁,释放系统资源。
5. 运行循环中的事件调度与性能优化
运行循环的一个重要特性是,任何队列中的事件都可能导致新的事件被调度到其他队列中。例如,Actions 队列中的事件可能会操作应用内的数据,而这些数据可能有自己的观察者或计算属性与之绑定。在这种情况下,新的事件会被添加到 Sync 队列中,以确保这些变化也能得到处理,然后运行循环才会移动到下一个队列。
这种机制确保了用户界面与数据变化保持一致,同时最大限度地减少了应用需要执行的 DOM 操作次数。通过合理安排事件的执行顺序,Ember.js 的运行循环能够提高应用的性能,尤其是在移动设备等处理能力有限的环境中。
以下是一个简单的示例,展示了如何手动调度事件到运行循环的队列中:
// 调度一个事件到 Sync 队列
Ember.run.schedule('sync', this, function() {
// 这里是需要在 Sync 队列中执行的代码
console.log('This event is scheduled in the Sync queue.');
});
// 调度一个事件到 AfterRender 队列
Ember.run.schedule('afterRender', this, function() {
// 这里是需要在 AfterRender 队列中执行的代码
console.log('This event is scheduled in the AfterRender queue.');
});
6. 总结
Ember.js 的运行循环是一个强大的机制,它通过预定义的队列来协调和执行应用中的事件、键值通知和定时器。运行循环的存在使得 Ember.js 应用能够保持响应性,确保数据绑定始终保持最新状态,同时通过减少 DOM 操作次数来提高性能。
在开发 Ember.js 应用时,了解运行循环的工作原理和各个队列的职责是非常重要的。开发者可以利用运行循环的机制来优化应用的性能,处理复杂的事件调度,以及确保用户界面与数据变化的一致性。
同时,在实现认证和授权时,使用第三方认证系统如 Mozilla Persona 可以带来诸多优势,但也需要注意遵循相关的安全指南,以确保应用的安全性。
通过合理运用运行循环和认证机制,开发者可以构建出高效、安全的 Ember.js 应用。
下面是一个总结运行循环各队列职责的表格:
| 队列名称 | 职责 |
| ---- | ---- |
| Sync | 处理传播绑定数据的操作 |
| Actions | 执行绑定传播完成后、视图渲染前的事件 |
| Render | 处理视图渲染到 DOM 的相关事件 |
| AfterRender | 执行标准渲染事件完成后的视图相关操作 |
| Destroy | 处理需要销毁的对象的事件 |
另外,再给出一个 mermaid 流程图,展示运行循环中事件调度的可能情况:
graph LR
A[Sync 队列] --> B[Actions 队列]
B --> C[Render 队列]
C --> D[AfterRender 队列]
D --> E[Destroy 队列]
A -.-> A1(可能添加新事件到其他队列)
B -.-> B1(可能添加新事件到其他队列)
C -.-> C1(可能添加新事件到其他队列)
D -.-> D1(可能添加新事件到其他队列)
E -.-> E1(可能添加新事件到其他队列)
这个流程图更清晰地展示了运行循环中各队列之间的关系以及事件调度的动态性。通过合理利用运行循环的机制,开发者可以更好地控制应用的执行流程,提高应用的性能和稳定性。
超级会员免费看
18

被折叠的 条评论
为什么被折叠?



