今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我们一睹为快!

例子

例子是官方的例子,加载一个英雄列表,点击显示详细信息。我直接放在我们的升级后的装备里面。

源代码

Injectable

在ng2里面如何编写服务呢?非常简单,你只需要写个类即可。那么这个@Injectable()是做什么的?其实单就这个例子来说,我们是不需要写个这个装饰的,因为我们的HeroSerivce没有依赖,如果你要写一个有依赖的服务,那么你需要加上这个@Injectable(),此处加上@Injectable()是可有可无的,但是写上是个好习惯。

app/hero.service.ts(部分代码)

@Injectable()
export class HeroService {
  getHeroes() {
    return Promise.resolve(HEROES);
  }
  // See the "Take it slow" appendix
  getHeroesSlowly() {
    return new Promise<Hero[]>(resolve =>
      setTimeout(() => resolve(HEROES), 2000) // 2 seconds
    );
  }
}

以上代码我们干了哪些事儿呢?

  1. 写了一个使用injectable装饰的类
  2. 写了两个成员函数
  3. 一个返回一个Promise,直接resolve数据
  4. 另一个也返回一个Promise,不过在两秒后resolve数据

有的同学会问:resolve的数据哪去了?Promise是什么?我们继续讲解。

Promise

如果你玩过ng1,你一定对promise不陌生,因为我们经常在路由里面写resolve,这里就可以接受一个Promise对象。还有ng1中的$q.defer()等等。

但是promise并不是ng1的专利,你可以在你的任何javascript程序中使用promise,因为在ES6中已经原生提供Promise对象。你可以查看它的用法,这里我简单描述下:

  1. 构造Promise,只需要在里面加入一个参数,这个参数是个function,这个function可以接受两个参数:resolve, reject。或者使用Promise.resolve(),不过这样没有延迟了。
  2. 使用Promise对象,最常用的方法是then(),里面接受一个function,这个function的参数为resolve的值。除了then()还有catch()等

为了让大家能够清晰的了解Promise的用法,我们打开chrome的console:

  1. 输入Promise,是个function。
  2. 输入Promise.resolve('123'),我们得到一个状态为“已经解决”的promise。
  3. 输入new Promise(resolve=>resolve('123')),我们还是得到一个状态为“已经解决”的promise。

2和3的区别在于,后者可以在参数的函数中做一些处理,比如延迟或者http请求。

然后让我们来看Promise的then方法:

  1. 首先我们写了一个已经resolved的promise,并将其赋值给p
  2. 然后使用p.then(),在回调函数里面打印参数,得到‘123’
  3. 最后p.then()整体返回的是个初始化(pending)的promise。

现在我们明白一下这个代码中promise的用法了吧?

app/hero.service.ts(部分代码)

@Injectable()
export class HeroService {
  getHeroes() {
    return Promise.resolve(HEROES);
  }
  // See the "Take it slow" appendix
  getHeroesSlowly() {
    return new Promise<Hero[]>(resolve =>
      setTimeout(() => resolve(HEROES), 2000) // 2 seconds
    );
  }
}

那么我们为何要使用promise呢?主要是为了解决回调地狱的问题。因为有了promise,你不必再写深层的回调,而是像极了同步的写法。

这是我的一个ng1的项目的部分代码,用promise的then()来解决回调地狱。

Auth.$createUser({email: email, password: pass})
                        .then(function() {
                            // authenticate so we have permission to write to Firebase
                            return Auth.$authWithPassword({ email: email, password: pass });
                        })
                        .then(function(user) {
                            // create a user profile in our data store
                            var ref = wdutil.ref('users', user.uid);
                            return wdutil.handler(function(cb) {
                                ref.set({email: email, name: $scope.name||firstPartOfEmail(email)}, cb);
                            });
                        })
                        .then(function(/* user */) {
                            $scope.wait.show=false;
                            // redirect to the account page
                            $location.path('/account');
                        }, function(err) {
                            $scope.wait.show=false;
                            $scope.alerts.push({type:'danger',msg:wdutil.errMessage(err)});
                        });

Interface

在编写这个服务的过程中我们使用了interface这个概念,这个知识点属于ts的范畴,我们通常在接口中声明类型,有点像react中的propTypes:

app/hero.ts

export interface Hero {
  id: number;
  name: string;
}

然后我们在我们的服务中使用了这个接口:

app/hero.service.ts(部分代码)

import {Hero} from './hero';

app/hero.service.ts(部分代码)

return new Promise<Hero[]>(resolve =>
      setTimeout(() => resolve(HEROES), 2000) // 2 seconds
    );

除此之外,我们在我们的组件里面也多次使用了这个接口:

app/app.component.ts

heroes: Hero[];
  selectedHero: Hero;

app/hero-detail.component.ts

export class HeroDetailComponent {
  hero: Hero;
}

到此为止,我们的服务就算是写好了!

使用服务

让我们在组件中测试一下我们写好的服务吧:

app/app.component.ts(部分代码)

import {HeroService} from './hero.service';

app/app.component.ts(部分代码)

providers: [HeroService]

app/app.component.ts(部分代码)

constructor(private _heroService: HeroService) { }

  getHeroes() {
    this._heroService.getHeroes().then(heroes => this.heroes = heroes);
  }

以上代码我们干了这些事儿:

  1. 利用模块系统导入这个服务类
  2. 在组件中注入这个服务
  3. 在构造函数中将这个服务赋给一个私有变量_heroService
  4. 然后就可以尽情地在类中使用这个服务对象了this._heroService

这里的getHeroes()返回了一个Promise,所以我们可以使用then来处理接下来要发生的事。


教程源代码及目录

如果您觉得本博客教程帮到了您,就赏颗星吧!

https://github.com/lewis617/angular2-tutorial

angular2系列教程(七)Injectable、Promise、Interface、使用服务的更多相关文章

  1. angular2系列教程(十)两种启动方法、两个路由服务、引用类型和单例模式的妙用

    今天我们要讲的是ng2的路由系统. 例子

  2. ASP.NET 5系列教程(七)完结篇-解读代码

    在本文中,我们将一起查看TodoController 类代码. [Route] 属性定义了Controller的URL 模板: [Route("api/[controller]") ...

  3. CRL快速开发框架系列教程七(使用事务)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  4. angular2系列教程(一)hello world

    今天我们要讲的是angular2系列教程的第一篇,主要是学习angular2的运行,以及感受angular2的components以及模板语法. 例子 这个例子非常简单,是个双向数据绑定.我使用了官网 ...

  5. 黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block 使用企业库异常处理应用程序模块的 ...

  6. webpack4 系列教程(七): SCSS提取和懒加载

    教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步>>> (原文)webpack4 系列教程(七): SCSS 提取和懒加载. 个人技术小站: https://god ...

  7. (转)NGUI系列教程七(序列帧动画UITexture 和 UIsprit)

    NGUI系列教程七(序列帧动画)   今天我给大家讲一下如何使用NGUI做序列帧动画.本节主要包括两方面内容,分别是使用UIspirit和使用UITexture 做序列帧动画.废话不说了,下面开始.还 ...

  8. 【转】PyQt5系列教程(七)控件

    PyQt5系列教程(七)控件   软硬件环境 Windows 10 Python 3.4.2 PyQt 5.5.1 PyCharm 5.0.4 前言 控件是PyQt应用程序的基石.PyQt5自带很多不 ...

  9. Unity3D脚本中文系列教程(七)

    http://dong2008hong.blog.163.com/blog/static/4696882720140311445677/?suggestedreading&wumii Unit ...

  10. NGUI系列教程七(序列帧动画)

    今天我给大家讲一下如何使用NGUI做序列帧动画.本节主要包括两方面内容,分别是使用UIspirit和使用UITexture 做序列帧动画.废话不说了,下面开始.还要在啰嗦一句,首先大家要准备一些序列帧 ...

随机推荐

  1. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

  2. 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino

    大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...

  3. Java 8五大主要功能为开发者提供了哪些便利?

    两年前当Java 8发布后,立即受到了业界的欢迎,因为它大大提高了Java的性能.它独特的卖点是,顾及了编程语言的每一个方面,包括JVM(Java虚拟机)和编译器,并且改良了其它帮助系统. Java是 ...

  4. ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起

    我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点.由于前面两章已经涵盖了依赖注入在管道构建过程中以及管道在处理请求过程的应用,但是内 ...

  5. SQLServer 版本之八大方法搞清 "我是谁"

    你正在使用 SQL Server 的哪个版本? 贴士:作为一个SQL Server数据库管理者或维护.支持人员,应该会经常问自己这样一个问题:我当前SQL Server版本号是?当前版本已经有的累计更 ...

  6. 获取微软原版“Windows 10 推送器(GWX)” 卸载工具

    背景: 随着Windows 10 免费更新的结束,针对之前提供推送通知的工具(以下简称GWX)来说使命已经结束,假设您还未将Windows 8.1 和Windows 7 更新到Windows 10 的 ...

  7. C# 给word文档添加水印

    和PDF一样,在word中,水印也分为图片水印和文本水印,给文档添加图片水印可以使文档变得更为美观,更具有吸引力.文本水印则可以保护文档,提醒别人该文档是受版权保护的,不能随意抄袭.前面我分享了如何给 ...

  8. JavaScript将字符串中的每一个单词的第一个字母变为大写其余均为小写

    要求: 确保字符串的每个单词首字母都大写,其余部分小写. 这里我自己写了两种方法,或者说是一种方法,另一个是该方法的变种. 第一种: function titleCase(str) { var new ...

  9. Android开发学习—— shape标签的使用

    参考这片文章http://www.cnblogs.com/armyfai/p/5912414.html

  10. 敏捷软件开发VS传统软件工程

    敏捷软件开发:又称敏捷开发,是一种从1990年代开始逐渐引起广泛关注的一些新兴软件开发方法,是一种应对快速变化的需求的一种软件开发能力. 与传统软件工程相比,它们的具体名称.理念.过程.术语都不尽相同 ...