Angular2学习笔记四(之Http通讯)

前言

接上篇,虽然一会儿从建立项目就到了http通讯,看上去是有点猴急,但没办法,走到哪里就算哪里吧。在这里,我描述三个场景,即系统的注册与登陆,及登陆后的操做。html

一、注册场景,前端页面传入用户名密码,经过一个api接口传到后台,在后台对这用户及密码进行保存;前端

二、登陆场景,前端用户传入用户名及密码,经过api接口传到后台,在后台进行配对,若是配对成功,则在后台派发(返回)一个令牌(id_token,下同),经过这个令牌做为用户已经登陆的惟一凭证,须要保存到用户本地存储(localStorage),之后做后续操做;node

三、登陆后操做,当用户须要受权操做时,那么首先得获取本地存储(localStorage)中的令牌,将令牌传到后台,若是匹配成功,则容许操做,不然不容许操做。git

之后三个场景大致描述了一个系统注册登陆的思路。下面,我将从这三个思路出发,讲述Angular2中http与后台通讯的过程。github

前期准备

在继续以前,咱们须要一些准备工做,即建立一个后台服务,包括注册、登陆及查询这三个接口。由于这里不关注后台怎么建立,因此我也从网上一位小哥这里找到现成的后台服务,这里包括有三个接口分别以下:npm

http://localhost:3001/users
http://localhost:3001/sessions/create
http://localhost:3001/api/protected/random-quote

下载及方法:json

git clone https://github.com/auth0/nodejs-jwt-authentication-sample.git
npm install
node server.js

按照上面的步骤,后台服务就算准备完成,能够继续往下看了。api

接下来,建立界面元素post-component.html服务器

<form (ngSubmit)="register(registerForm.value)" #registerForm="ngForm">
  <div class="text-center">
    <h2>注册</h2>
  </div>
  <div class="form-group">
    <label for="username">Name</label>
    <input type="text" class="form-control" id="username" required [(ngModel)]="model.username" name="username">
  </div>
  <div class="form-group">
    <label for="password">Alter Ego</label>
    <input type="text" class="form-control" id="password" required [(ngModel)]="model.password" name="password">
  </div>
  <button type="submit" class="btn btn-success">Submit</button>
</form>

<form (ngSubmit)="onLogin(loginForm.value)" #loginForm="ngForm">
  <div class="text-center">
    <h2>登陆</h2>
  </div>
  <div class="form-group">
    <label for="username2">Name</label>
    <input type="text" class="form-control" id="username2" required [(ngModel)]="model.username2" name="username2">
  </div>
  <div class="form-group">
    <label for="password2">Alter Ego</label>
    <input type="text" class="form-control" id="password2" required [(ngModel)]="model.password2" name="password2">
  </div>
  <button type="submit" class="btn btn-success">Submit</button>
</form>

<button id="input" (click)="getSecretQuote()">登陆以后才能获取数据</button>

接下来建立PostComponent.ts组件session

@Component({
      selector: 'post-client',
      templateUrl: './post-component.html',
    })
    
    export class PostComponent {
      model: any;

      constructor(private http: Http) {
        this.model = {};
      }
      //把代码写这里啦
    }

这样,咱们就已经建立好工做区模板,能够尽情在哪里写东西了。

再准备准备

在进行以前,咱们看下angular2中,http api方法的传参数形式

http.get(url: string, options?: RequestOptionsArgs) : Observable<Response>
http.post(url: string, body: any, options?: RequestOptionsArgs) : Observable<Response>

能够看到,根据其参数url地址, body:any及options?: RequestOptionsArgs参数来提交对应的数据信息,其中body表示传递到服务器端的数据信息,options表示头部验证信息。两个方法都返回一个可观察对象Observable,咱们能够经过subscribe方法获得里面的值并做后继处理。这样,咱们能够获得如下代码处理方法

this.http.post(url: string, body: any, options?: RequestOptionsArgs).subscribe(function (data) {
   console.log(data)
})

以上的处理方式并无什么太大的问题,但总感受仍是有点小小的欠缺。

结果处理之可观察对象Observable

咱们经过Http以及Jsonp的api接口能够知道,默认返回值都是可观察对象 Observable< Response >。能够把可观察对象 Observable 看作一个由某些“源”发布的事件流。 经过 订阅 到可观察对象 Observable ,咱们监听(subscribe)这个流中的事件。 在这些订阅中,咱们指定了当 Web 请求生成了一个成功事件 ( 有效载荷是英雄数据 ) 或失败事件 ( 有效载荷是错误对象 ) 时该如何采起行动,如示例中所示。

咱们的服务能够返回 HTTP 响应对象Response。但这可不是一个好主意! 数据服务的重点在于,对消费者隐藏与服务器交互的细节。其实上,咱们最关心的仍是获取到的返回数据信息,这时候咱们就能够利用RxJS库来对事件流进行一些额外的处理。

RxJS("Reactive Extensions" 的缩写)是一个被 Angular 承认的第三方库,它实现了异步可观察对象 (asynchronous observable) 模式。Rxjs库中包含不少对事件流进行处理的方法,例如map,distinctUntilChanged等操做符。

针对返回数据是json格式的响应对象,能够把Response解析成 JavaScript 对象——只要调一下 response.json() 就能够了,这时候咱们就能够利用map操做符来进行处理,例如,咱们将上面的方法升级下

this.http.post(url: string, body: any, options?: RequestOptionsArgs).map((rsp:Response)=>{
return rsp.json()
})
.subscribe((data) => {
console.log(data);
});

注意,这里.map用到了rxjs库,须要导入这个库。

结果处理之Promise

虽然 Angular 的 http 客户端 API 返回的是 Observable<Response> 类型的对象,但咱们也能够把它转成 Promise<Response>。这很容易,只须要调用可观察对象 Observable< Response >的方法toPromise()就可以进行转化。

this.http.post(url: string, body: any, options?: RequestOptionsArgs).toPromise()
.then((rsp: Response) => {
console.log(rsp)
});

注册

经过上面的讲述,如今执行http通讯也变得简单多了。上代码

register(data) {
    var username = data.username;
    var password = data.password;
    var body = "username=" + username + "&password=" + password + "&extra=color";
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    this.http.post('http://localhost:3001/users', body, {
      headers: headers
    })
      .map(res => res.json())
      .subscribe(
        data => console.log(data),
        err => console.log(err),
        () => console.log('Register Complete')
      );
  }

登陆

onLogin(data) {
    var username = data.username2;
    var password = data.password2;
    var body = "username=" + username + "&password=" + password + "&extra=color";
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    this.http.post('http://localhost:3001/sessions/create', body, {
      headers: headers
    })
      .map(res => res.json())
      .subscribe(
        data => {
          localStorage.setItem('id_token', data.id_token), console.log(data)
        },
        err => console.log(err),
        () => console.log('Register Complete')
      );
  }

这里须要注意,localStorage.setItem('id_token', data.id_token)这句代码,表明将获取的令牌保存到本地存储,这是表明本用户已经登陆的惟一凭证。

查询

getSecretQuote() {

    var jwt = localStorage.getItem('id_token');
    var authHeader = new Headers();
    if (jwt) {
      authHeader.append('Authorization', 'Bearer ' + jwt);
    }

    this.http.get('http://localhost:3001/api/protected/random-quote', {
      headers: authHeader
    })
      .map(res => res.text())
      .subscribe(
        data => console.log(data),
        err => console.log(err),
        () => console.log('Secret Quote Complete')
      );

  }

在这里,执行查询前须要把本地存储中的令牌带到头部,

var jwt = localStorage.getItem('id_token');

这样后台就能够在查询前对令牌进行比对,若是比对成功,则返回结果。

这样,一个简单的注册--登陆--查询思路便讲解完成了

Angular2 Http注册登陆验证

Angular2 Http

相关文章
相关标签/搜索