本节介绍了路由器的一些更高级的功能和处理复杂异步逻辑的能力。

一、A word on promises

1. 在Ember的Router中Ember使用了大量的Promises概念来处理异步逻辑。简而言之,promises就是一个代表最终值的对象。一个promise可以fulfill(成功解析值)或者reject(解析值失败)。

2. 检索这个最终值的方法或者当promise reject的时候处理这些情况是通过promise的then方法。then方法接受两个可选的回调,一个是为了fulfillment,另外一个是为了rejection。

3.如果promise执行,fulfillment handler被调用并且用fulfilled value作为唯一的参数,如果promise被拒绝了,rejection handler会被调用并把拒绝的原因reason for the rejection作为它的唯一参数:

example:

var promise = fetchTheAnswer();

promise.then(fulfill, reject);

function fulfill(answer) {
console.log("The answer is " + answer);
} function reject(reason) {
console.log("Couldn't get the answer! Reason: " + reason);

4. promises大部分的力量来自于一个事实,它们可以被链接在一起执行顺序的异步操作:

// Note: jQuery AJAX methods return promises
var usernamesPromise = Ember.$.getJSON('/usernames.json'); usernamesPromise.then(fetchPhotosOfUsers)
.then(applyInstagramFilters)
.then(uploadTrendyPhotoAlbum)
.then(displaySuccessMessage, handleErrors);
  • 在上面的例子中,如果fetechPhotosOfUsers, applyInstagramFilters, 或者uploadTrendyPhotoAlbum方法中的任何一个返回一个reject promisehandleErrors将会携带着失败的原因被调用。
  • 以这种方式,promises近似异步形式的try-catch语句,防止嵌套回调后嵌套回调向右流,并且促进一个更明智的方法来管理应用程序中复杂的异步逻辑。

5. guid中不打算完全深入到可以使用所有不同方式的promises,但是如果你想更深入的学习,请查看RSVP,它是Ember使用的promise库。

二、The router pauses for promises

1. 当在路由器之间跳转的时候,Ember路由器收集所有的在跳转结束时被传递给路由controllers的models(通过model hook)。

如果model hook(或者相关的beforeModel, afterModel hooks)返回正常的(non-promise)的对象或者数组,跳转将会立即完成。

但是如果model hook(或者相关的beforeModel, afterModel hooks)返回了一个promise(或者如果一个promise被作为一个提供给transitionTo的参数),跳转将会暂停,直到这个promise执行(fullfill)或者被拒绝(reject)。

2. 路由器考虑把任何有then方法的对象定义成一个promise

3. 如果这个promise执行了(fullfill),跳转将到它离开的地方并开始解析下一个路由的model。

4. 一个基本的例子:

app/routes/tardy.js

export default Ember.Route.extend({
model() {
return new Ember.RSVP.Promise(function(resolve) {
Ember.run.later(function() {
resolve({ msg: "Hold Your Horses" });
}, 3000);
});
}, setupController(controller, model) {
console.log(model.msg); // "Hold Your Horses"
}
});
  • 当跳转进入route:tardymodel hook将被调用并且返回一个promise,它不会被解析直到3秒之后,在这期间路由器将暂停在中间跳转。
  • 当promise最终实现了,路由器将会继续跳转并且最终调用route:tardysetupController hook,带着解析后的对象。

5. 当你需要保证在展示一个新模板之前路由的数据完全被加载,这种pause-on-promise是非常有价值的。

三、When promises reject...

我们已经涵盖了一个model promise履行的情况下,但如果它拒绝?

1. 默认的,如果一个model promise在跳转之间被拒绝,跳转就被终止,没有新的目标路由模板被渲染,并将错误记录到控制台。

2. 你可以通过在路由的actions hash中的error handler来配置错误处理程序。当一个promise被拒绝,一个error事件将会在路由上被激活并且冒泡到route:application的默认错误处理程序上,除非它通过一个自定义错误处理器的方式被处理。

3. example:

app/routes/good-for-nothing.js

export default Ember.Route.extend({
model() {
return Ember.RSVP.reject("FAIL");
}, actions: {
error(reason) {
alert(reason); // "FAIL" // Can transition to another route here, e.g.
// this.transitionTo('index'); // Uncomment the line below to bubble this error event:
// return true;
}
}
});
  • 在上面的例子中,错误事件将会停止在route:good-for-nothing的错误处理程序中并且不会继续不冒泡。
  • 为了使事件继续冒泡到route:application,你可以返回从错误处理程序中返回true

四、Recovering from rejection

拒绝的model promise终止跳转,但是因为promises是连贯性的,你可以在model hook中捕捉到拒绝的promise它自己,并且把它们转换为实现,这不会终止跳转。

app/routes/funky.js

export default Ember.Route.extend({
model() {
return iHopeThisWorks().then(null, function() {
// Promise rejected, fulfill with some default value to
// use as the route's model and continue on with the transition
return { msg: "Recovered from rejected promise" };
});
}
});

五、Beforemodel and Aftermodel

1. 对于pause-on-promise跳转,model hook包含了多个用例,但有时你将需要相关的beforeModelafterModel hooks的帮助。最普遍的原因就是,如果通过{{link-to}}或者transitionTo(而不是由一个网址变化引起的变化)你跳转到一个含有动态URL字段的路由,这个你正在跳转的路由的model已经被指定了(例如{{#link-to 'article' article}} or this.transitionTo('article', article)),在这种情况下model hook不会被调用。

在这种情况下,你需要使用beforModel或者afterModel hook来存储逻辑,同时路由器仍然在收集所有路由的models来执行跳转。

2. beforModel

很容易对两者比较有用的,beforeModel hook在路由器尝试为给定的路由解析model之前会被调用。换句话说,它在model hook被调用之前被调用,或者如果model没有被调用,它在路由器尝试解析任何传递给这个路由的model promises之前被调用。

比如model,从beforeModel返回一个promise将会暂停跳转直到它被解析,或者如果被拒绝将会激活一个eroor

3. 下面是一个用例的far-from-exhaustive列表,这里beforeModel是非常方便的:

  • model中执行一个潜在的浪费服务器的查询之前决定是否重定向到其他的路由。
  • 确保用户在前进到model之前具有身份验证令牌。
  • 加载次路由要求的应用程序代码
  • app/routes/secret-articles.js
export default Ember.Route.extend({
beforeModel() {
if (!this.controllerFor('auth').get('isLoggedIn')) {
this.transitionTo('login');
}
}
});

4. afterModel

1. afterModel hook在一个route's model(可能是一个promise)被解析之后被调用,并且遵循和beforeModel同样的pause-on-promise语法作为model。它被传递到已经被解析的model,并且因此,执行任何依赖于完全解析的model的值的额外的逻辑。

2. example

app/routes/articles.js

export default Ember.Route.extend({
model() {
// `this.store.findAll('article')` returns a promise-like object
// (it has a `then` method that can be used like a promise)
return this.store.findAll('article');
},
afterModel(articles) {
if (articles.get('length') === 1) {
this.transitionTo('article.show', articles.get('firstObject'));
}
}
});

3. 你也许会问,为什么我们不能只是把afterModel逻辑放入从model返回的promise的fulfill handler: 原因是,正如上面所提到的,跳转通过{{link-to}}或者transitionTo初始化,很可能已经为路由提供了model,所以model在这些情况下不能被调用。

4.10 Routing -- Asynchronous Routing的更多相关文章

  1. Asp.Net MVC 3【URLs, Routing,and Areas】续

    http://www.cnblogs.com/HuiTai/archive/2012/07/24/2597875.html 接着前面继续学习分享我们的路由. 现在我们把Global.asax文件里的R ...

  2. Source Routing

    Source routing Followed by book_Principles and Practices of Interconnection Networks, p204. With sou ...

  3. PatentTips - Highly-available OSPF routing protocol

    BACKGROUND OF THE INVENTION FIG. 1A is a simplified block diagram schematically representing a typic ...

  4. Troubleshooting routing topology based on a reference topology

    In one embodiment, a computing device (e.g., border router or network management server) transmits a ...

  5. Fast-tracking approach for building routing topologies in fast-moving networks

    In one embodiment, a local node in a communication network determines a set of its neighbor nodes, a ...

  6. elasticsearch routing

    当索引一个文档的时候,文档会被存储到一个主分片中. Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?当我们创建文档时,它如何决定这个文档应当被存储在分片 1 还是分片 2 中呢?首 ...

  7. Endless looping of packets in TCP/IP networks (Routing Loops)

    How endless looping of packets in a TCP/IP network might occur? Router is a device used to interconn ...

  8. elasticsearch 自定义routing

    由于线上elasticsearch集群数据量越来越大,优化已经已经是重中之重. 优化的方式有很多中,网上一大堆,自行百度. 优化方案中有个叫routing的方案是个需要熟悉业务日志才能使用.于是我就研 ...

  9. ASP.NET MVC Routing学习笔记(一)

    Routing在ASP.NET MVC中是非常核心的技术,属于ASP.NET MVC几大核心技术之一,在使用Routing之前,得先引入System.Web.Routing,但其实不用这么麻烦,因为在 ...

随机推荐

  1. [转]ASP.NET MVC 5 - 添加一个模型

    在本节中,您将添加一些类,这些类用于管理数据库中的电影.这些类是ASP.NET MVC 应用程序中的"模型(Model)". 您将使用.NET Framework 数据访问技术En ...

  2. Android中SurfaceView用法示例

    SurfaceView在游戏开发中有着举足轻重的地位,它对于画面的控制有着更大的自由度(不像View要用handler来更新,关于View的),但这方面的参考资料并不是太多,能找到的例子都有点喧宾夺主 ...

  3. 第二篇:一个经典的比喻( 关于TCP连接API )

    前言 编程是对现实世界的模拟,网络通信自然也是对现实世界通信的模拟.可以将网络通信中使用的各种API和对现实世界中的各种通信设备进行通讯的操作进行对比以加深理解. 对比 socket() 函数 vs ...

  4. XMPP HTTP

    1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上 ...

  5. 在腾讯云服务器上体验Docker

    版权声明:本文由姚俊刚原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/85 来源:腾云阁 https://www.qclou ...

  6. JZOJ.5329【NOIP2017模拟8.22】时间机器

    Description

  7. Java初学者笔记六:反射

    Java反射基础 零.基础类代码 import java.io.*; import java.lang.reflect.*; class father{ public String fName; fa ...

  8. 【Enterprise Architect 】

    [Enterprise Architect ]Enterprise Architect 8 key {67SC0O95-SZPS-LIG2-YQ8Q-8D2N-KWTD-0W6R-TWDD-KT6RB ...

  9. 监控linux流量shell版

    想要实时查看linux流量情况,又不想再去下第三方工具,可以直接写脚步运行! 系统:centos 6.5 原理:从/proc/net/dev中获取到流量情况,再通过换算并除以间隔时间来得到流量单位M ...

  10. eclipse 安装Subversion1.82(SVN)插件

    Eclipse下SVN插件的安装,可以选择在线安装和离线安装两种方式: 2.(可选①)使用本地安装包安装插件 --填写插件名(可随意取名) --插件来源地址(①安装包,②使用网址) →Archie→选 ...