Angular2入門系列教程7-HTTP(一)-使用Angular2自帶的http進行網絡請求

上一篇:Angular2入門系列教程6-路由(二)-使用多層級路由並在在路由中傳遞複雜參數css


    感受這篇不是很好寫,由於涉及到網絡請求,若是採用真實的網絡請求,這個例子你們拿到手估計還要本身寫一個web api來提供調用;好在Angular2提供了本地模擬的api,能夠供咱們編寫方便;可是,真實使用的狀況每每與本地模擬有一些差異,會存在跨域等一系列問題;這些不在本篇文章的講解範圍以內,若是在.net下遇到跨域問題能夠直接私信我。html

    Angular的http模塊並非Angular2的核心模塊,你並不必定要使用它;咱們有不少替代方案,好比你可使用jQuery的ajax,又或是本身編寫網絡請求;這都不重要,你不學習這一節的內容並不會影響你使用Angulargit

    假設你已經跟上了咱們的進度,那,就開始吧github

    首先咱們得要創建一個模擬的api文件,在咱們的data目錄下,內容以下web

    

 1 import { InMemoryDbService } from 'angular-in-memory-web-api';
 2 export class InMemoryDataService implements InMemoryDbService {
 3   createDb() {
 4      let blogs=[
 5     { id:1,title:"號外號外?奧巴馬要下臺啦",profile:"唐納德·特朗普,第45任美國總統,1946年6月14日生於美國紐約,政治家、商人、做家、主持人。特朗普1968年從賓夕法尼亞大學"},
 6     { id:2,title:"什麼?奧巴馬要下臺啦?",profile:"除房地產外,特朗普將投資範圍延伸到其餘行業,包括開設賭場、高爾夫球場等。他還涉足娛樂界,是美國真人秀《名人學徒》等電視節目的主持人"},
 7     { id:3,title:"號外號外?川普要上臺了",profile:"特朗普在過去20年間分別支持過共和黨和民主黨各主要總統競選者。2015年6月,特朗普以共和黨競選者身份正式參加2016年美國總統選舉。此前,特朗普沒有擔任過公共職務"},
 8     { id:4,title:"啥?我大四川人也要當美國總統了?",profile:"2016年11月9日,美國大選計票結果顯示:共和黨候選人唐納德·特朗普已得到了276張選舉人票,超過270張選舉人票的獲勝標準,當選美國第45任總統"},
 9     { id:5,title:"mdzz,一羣麻瓜,通通查殺",profile:"1946年6月14日,特朗普在紐約市出生,排行老二,上有一個姐姐,下有兩個弟弟、一個妹妹。因爲祖父英年早逝,父親"},
10     { id:6,title:"首推龍文,必須出具",profile:"父母親友的愛心呵護下,特朗普自幼即滿腹自信,活力四射,沒法靜下來用功讀書。13歲那年,父母只好送他去「紐約軍事學校」求學,冀望軍校的嚴格訓練能幫助他力爭上游。在軍校就讀期間,特朗普"}
11 ]
12     return {blogs};
13   }
14 }

    這裏有些朋友會遇到  找不到 angular-in-memory-web-api 這個模塊的錯誤,咱們在package.json裏面添加這段代碼,"angular-in-memory-web-api": "~0.1.13",ajax

位置在"devDependencies"下面,而後在命令行npm install一下npm

   ok,這裏就是咱們的新的數據來源,那麼要如何使用呢?json

   先到app.module.ts中配置,這裏貼出所有代碼吧bootstrap

    

 1 import { BrowserModule } from '@angular/platform-browser';
 2 import { NgModule } from '@angular/core';
 3 import { FormsModule } from '@angular/forms';
 4 import { HttpModule } from '@angular/http';
 5 import { AppRoutingModule } from './app.routing';
 6 import { ArticleDetailRoutingModule } from './articledetail.routing';
 7 //in memery
 8 import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
 9 import { InMemoryDataService }  from './data/in-memery-data.service'
10 
11 import {BlogService} from './data/blog.service';
12 import {CommentService} from './data/comment.service';
13 
14 import { AppComponent } from './app.component';
15 import { ArticleComponent } from './article/article.component';
16 import { ArticledetailComponent } from './articledetail/articledetail.component';
17 import { CommentComponent } from './comment/comment.component';
18 
19 
20 @NgModule({
21   declarations: [
22     AppComponent,
23     ArticleComponent,
24     ArticledetailComponent,
25     CommentComponent
26     
27   ],
28   imports: [
29     BrowserModule,
30     FormsModule,
31     HttpModule,
32     ArticleDetailRoutingModule,
33     InMemoryWebApiModule.forRoot(InMemoryDataService),//in memery
34     AppRoutingModule
35 
36   ],
37   providers: [BlogService,CommentService],
38   bootstrap: [AppComponent]
39 })
40 export class AppModule { }
View Code

有備註的話我就不解釋什麼了,就是模塊導入而已api

 

接下來,在咱們的blog.service.ts裏面使用http去獲取這些數據

要使用Angular2的http服務,首先要導入它

import {Http,Response ,Headers} from "@angular/http";

Http就是http請求模塊,至於Response的話是返回值類型,Headers是請求頭的配置,這個咱們在以後會用獲得;

    必須說明一下的是,Angular2的get http請求的返回值都是Observable類型的,這是。。。Observable(可觀察對象)是一個管理異步數據流的強力方式。。不少概念,這個之後再講吧。咱們這裏經過rxjs將它轉爲一個Promise對象,Promise相對來講好理解一些,在一個Promise有告終果時,它承諾會回調咱們,咱們請求一個異步服務去作點什麼,而且給它一個回調函數。 當Promise的工做一旦完成,它就會調用咱們的回調函數,並經過參數把工做結果或者錯誤信息傳給咱們;詳細信息的話能夠自行搜索;

好,如今來改造咱們的blog.service.ts

import { Injectable } from '@angular/core';
import {Http,Response ,Headers} from "@angular/http";

import 'rxjs/Rx';

import { Blog,BLOGS } from './blog';

@Injectable()
export class BlogService {
  private apiUrl="app/blogs";
  private headers = new Headers({'Content-Type': 'application/json'});
  
  constructor(private http:Http){}

  getBlogs():Promise<Blog[]> {
    return this.http.get(this.apiUrl)
    .toPromise()
    .then(r=> r.json().data as Blog[]); //BLOGS;
  }
  getSelectedBlog(id:number):Promise<Blog>
  {
    let blog=new Blog();
    return this.getBlogs().then(blogs=>blogs.find(x=>x.id==id));
  }

  create(title: string):Promise<Blog> {
     return this.http
      .post(this.apiUrl, JSON.stringify({title: title}), {headers: this.headers})
      .toPromise()
      .then(res => res.json().data);
      
  }

  editBlog(blog:Blog)
  {
    let editBlog= BLOGS.find(x=>x.id==blog.id);
    editBlog=blog;
  }
  addBlog(blog:Blog):string
  {
    var maxId=0;
    BLOGS.forEach(x=>{
        if(x.id>maxId)
          maxId=x.id;
     });
     blog.id=maxId;
     if(blog.title.length==0)
     {
       return "title 不能未空";
     }
     else{
       BLOGS.push(blog);
       return "success";
     }
  }
}

   要將結果轉爲Promise,咱們須要導入rxjs,代碼如上

    其餘咱們在構造函數中注入了http模塊,而後使用了它,咱們這裏就簡單得使用了get和post兩種方式,固然,Angualr2提供了put以及delete,用法都同樣,這裏就很少舉例了;上面的post方法使用了JSON.stirngify來處理咱們的參數,實際狀況中,咱們能夠直接將一個Object類型傳過去就好了,相似與下面的代碼

create(blog: Blog):Promise<Blog> { return this.http .post(this.apiUrl, blog, {headers: this.headers}) .toPromise() .then(res => res.json().data); }

Angular會幫咱們處理這些數據

Angular默認的請求方式是 header {'Content-Type': 'application/json'};若是須要其餘請求類型,須要本身指定;可是,Angular2最終也會將請求的參數處理爲一個Json,至於你的後臺要用什麼去接收,那就是你的事情了。

本篇文章中的本地模擬api的地址,以及操做方法爲何能成功你並不用關心,這只是用做例子而已,實際開發中並不會這樣,若是你有真實的api,那就請使用真實的api吧。

因爲咱們將返回類型修改成了Promise,那麼咱們之前的組件裏面的代碼也須要修改,首先是

article.component.ts

 1 import { Component } from '@angular/core';
 2 import {BLOGS,Blog} from '../data/blog';
 3 import {BlogService} from './../data/blog.service';
 4 
 5 import {Observable} from 'rxjs';
 6 
 7 @Component({
 8     selector: 'ngarticle',
 9     templateUrl: './article.component.html',
10     styleUrls:['./article.component.css']
11 })
12 
13 export class ArticleComponent  {
14     blogList:Blog[];
15     selectedBlog:Blog;
16     editStr:string;
17     constructor(private bService:BlogService)
18     {
19         bService.getBlogs().then(x=>{this.blogList=x});
20     }
21     selectBlog(id:number)
22     {
23         this.bService.getSelectedBlog(id).then(blog=>{this.selectedBlog=blog;console.log(blog);});
24     }
25     doAdd()
26     {
27        if(this.editStr.length>0)
28        {
29          this.bService.create(this.editStr)
30           .then(x=>{
31          this.blogList.push(x);this.editStr=""
32          });
33        }
34    }
35 }

這裏咱們額外處理了一個新增文章的操做,那,咱們到html頁面添加一個按鈕

 1 <div class="article">
 2     <ul class="articleList">
 3             <li *ngFor="let blog of blogList" [routerLink]="['/articledetail',blog.id]" >
 4                 <a>
 5                    {{blog.id}}:{{blog.title}}
 6                 </a>
 7             </li>
 8     </ul>
 9     <div>
10 </div>
11 <div class="container">
12     <div class="row">
13         <button class="btn" (click)="doAdd()">新增文章</button>
14         <input type="text" class="input" [(ngModel)]="editStr">
15     </div>
16 </div>

接下來咱們處理下articleDetail.component.ts就好了

因爲只修改了ngOnInit,這裏就不貼那麼多代碼了

1 ngOnInit() {
2         let id=this.aRoute.params
3         .switchMap((params: Params) =>this.bService.getSelectedBlog(+params['id']))
4         .subscribe(x=>this.blog=x)
5      }

到此,咱們的網絡請求一塊就能夠正常工做了

    

因爲Angualr2的http涉及到一些額外的處理方式,包括Promise和Observable,這使得不少人剛開始會很不適應;可是Angular並不強制你使用這些,你可使用本身的請求方式;可是使用rxjs能帶來很強的流處理方式,這些都須要深刻學習以後才能體會到,若是你的項目對異步等要求沒那麼強,你能夠直接使用promise或者直接用ajax都是可行的,具體看你的項目需求。以後可能會帶來關於RxJs的教程,可能

更新ing。。。


 

項目已經放到了gitbub上,地址 https://github.com/SeeSharply/LearnAngular

本文章的提交 https://github.com/SeeSharply/LearnAngular/tree/b6396476023bb388b93bfd6f922374f790a71786

相關文章
相關標籤/搜索