In a previous post about testing I mentioned that route resolves can make authoring unit tests for a controller easier. Resolves can also help the user experience.

A resolve is a property you can attach to a route in both ngRoute and the more robust UI router. A resolve contains one or more promises that must resolve successfully before the route will change. This means you can wait for data to become available before showing a view, and simplify the initialization of the model inside a controller because the initial data is given to the controller instead of the controller needing to go out and fetch the data.

As an example, let’s use the following simple service which uses $q to simulate the async work required to fetch some data.

app.factory("messageService", function($q){
    return {
        getMessage: function(){
            return $q.when("Hello World!");
        }
    };
});

And now the routing configuration that will use the service in a resolve.

$routeProvider
    .when("/news", {
        templateUrl: "newsView.html",
        controller: "newsController",
        resolve: {
            message: function(messageService){
                return messageService.getMessage();
        }
    }
})

Resolve is a property on the routing configuration, and each property on resolve can be an injectable function (meaning it can ask for service dependencies). The function should return a promise.

When the promise completes successfully, the resolve property (message in this scenario) is available to inject into a controller function. In other words, all a controller needs to do to grab data gathered during resolve is to ask for the data using the same name as the resolve property (message).

app.controller("newsController", function (message) {
    $scope.message = message;
});

You can work with multiple resolve properties. As an example, let’s introduce a 2nd service. Unlike the messageService, this service is a little bit slow.

app.factory("greetingService", function($q, $timeout){
   return {
       getGreeting: function(){
           var deferred = $q.defer();
           $timeout(function(){
               deferred.resolve("Allo!");
           },2000);
           return deferred.promise;
       }
   }
});

Now the resolve in the routing configuration has two promise producing functions.

.when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        message: function(messageService){
            return messageService.getMessage();
        },
        greeting: function(greetingService){
            return greetingService.getGreeting();
        }
    }
})

And the associated controller can ask for both message and greeting.

app.controller("newsController", function ($scope, message, greeting) {
    $scope.message = message;
    $scope.greeting = greeting;
});

Composing Resolve

Although there are benefits to moving code out of a controller, there are also drawbacks to having code inside the route definitions. For controllers that require a complicated setup I like to use a small service dedicated to providing resolve features for a controller. The service relies heavily on promise composition and might look like the following.

app.factory("newsControllerInitialData", function(messageService, greetingService, $q) {
    return function() {
        var message = messageService.getMessage();
        var greeting = greetingService.getGreeting();
 
        return $q.all([message, greeting]).then(function(results){
            return {
                message: results[0],
                greeting: results[1]
            };
        });
    }
});

Not only is the code inside a service easier to test than the code inside a route definition, but the route definitions are also easier to read.

.when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        initialData: function(newsControllerInitialData){
            return newsControllerInitialData();
        }
    }
})

And the controller is also easy.

app.controller("newsController", function ($scope, initialData) {
    $scope.message = initialData.message;
    $scope.greeting = initialData.greeting;
});

One of the keys to all of this working is $q.all, which is a beautiful way to compose promises and run requests in parallel.

routeProvider的更多相关文章

  1. AgularJS中Unknown provider: $routeProvider解决方案

    最近在学习AgularJS, 做到http://angularjs.cn/A00a这一步时发现没有办法执行路由功能, 后来翻看控制台日志,发现提示Unknown provider: $routePro ...

  2. routeProvider路由的使用

    先创建一个主程序文件index.html,内容如下: <!DOCTYPE html> <html ng-app="myApp"> <head> ...

  3. angularJS $routeProvider

    O'Reilly书上的伪代码 var someModule = angular.module('someModule',[...module dependencies]); someModule.co ...

  4. AngularJS---Unknown provider: $routeProvider

    AngularJS路由报错: Unknown provider: $routeProvider 根据先知们的指引,在网上爬贴,有翻到官方的解决文章. 原来在AgularJS1.2.0及其之后的版本中, ...

  5. 26.angularJS $routeProvider

    转自:https://www.cnblogs.com/best/tag/Angular/ O'Reilly书上的伪代码 var someModule = angular.module('someMod ...

  6. AngularJS实例实战

    学习了这么多天的AngularJS,今天想从实战的角度和大家分享一个简单的Demo--用户查询系统,以巩固之前所学知识.功能需求需要满足两点 1.查询所有用户信息,并在前端展示 2.根据id查询用户信 ...

  7. Nodejs之MEAN栈开发(七)---- 用Angular创建单页应用(下)

    上一节我们走通了基本的SPA基础结构,这一节会更彻底的将后端的视图.路由.控制器全部移到前端.篇幅比较长,主要分页面改造.使用AngularUI两大部分以及一些优化路由.使用Angular的其他指令的 ...

  8. Nodejs之MEAN栈开发(六)---- 用Angular创建单页应用(上)

    在上一节中我们学会了如何在页面中添加一个组件以及一些基本的Angular知识,而这一节将用Angular来创建一个单页应用(SPA).这意味着,取代我们之前用Express在服务端运行整个网站逻辑的方 ...

  9. AngularJs之八

    ***今天讲一下angularJs的路由功能: 一:angularJs路由. 1.AngularJS 路由允许我们通过不同的 URL 访问不同的内容. 2.通过 AngularJS 可以实现多视图的单 ...

随机推荐

  1. ios7适配一些问题以及64位32位

    ios7适配一些问题(http://www.cocoachina.com/ios/20130703/6526.html) 1.iOS应用如何实现64位的支持 http://www.codeceo.co ...

  2. Web服务器异常问题记录

    1.使用命令,出现"-bash: 命令: Input/output error" 重启服务器后正常,网上查了下是说硬盘写入读取异常,经过和服务器厂商沟通后,确认是硬件问题导致(硬盘 ...

  3. 网络性能测试工具iperf详细使用图文教程【转载】

    原文:http://blog.163.com/hlz_2599/blog/static/142378474201341341339314/ 参考:http://man.linuxde.net/iper ...

  4. 转:浅谈C/C++中的指针和数组(一)

    再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ...

  5. SDL2.0的几何图行绘画

    SDL2.0的几何图形绘画 通过SDL_Window.SDL_Renderer.SDL_Texture三者实现了简单的几何图形绘画. 包括了SDL_RenderDrawPoint.SDL_Render ...

  6. 转!数据库连接池概念、种类、配置(DBCP\C3P0\JndI与Tomact配置连接池)

    数据库连接池概念.种类.配置(DBCP\C3P0\JndI与Tomact配置连接池) 一.DBCP 连接:DBCP 连接池是 Apache 软件基金组织下的一个开源连接池实现. 需要的 java 包c ...

  7. zImage转换为uImage

    写个随笔,备忘! 拿到一个内核后,首先将其make为zImage,步骤: 1.将与要移植的系统的配置文件拷贝给.config cp xxx_xxx .config 2.修改Makefile,指定平台构 ...

  8. 聊天界面之气泡文本cell(一)

    在实现qq聊天界面的过程中,使用UITableViewCell碰到了不少问题,这里还是记录一下以免遗忘. 气泡聊天cell的实现,网上最多的方法还是: 1.手动计算设置frame的值,文本的size使 ...

  9. LinuxShell脚本攻略--第三章 以文件之名

    生成任意大小的文件文件权限.所有权和粘滞位创建不可修改文件生成空白文件查找符号链接及其指向目标head 与 tail只列出目录的其他方法在命令行中用 pushd 和 popd 快速定位(cd -)统计 ...

  10. Android相机开发那些坑

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