Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web api来提供调用;好在Angular2提供了本地模拟的api,可以供我们编写方便;但是,真实使用的情况往往与本地模拟有一些差别,会存在跨域等一系列问题;这些不在本篇文章的讲解范围之内,如果在.net下遇到跨域问题可以直接私信我。
Angular的http模块并不是Angular2的核心模块,你并不一定要使用它;我们有很多替代方案,比如你可以使用jQuery的ajax,又或是自己编写网络请求;这都不重要,你不学习这一节的内容并不会影响你使用Angular
假设你已经跟上了我们的进度,那,就开始吧
首先我们得要建立一个模拟的api文件,在我们的data目录下,内容如下
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",
位置在"devDependencies"下面,然后在命令行npm install一下
ok,这里就是我们的新的数据来源,那么要如何使用呢?
先到app.module.ts中配置,这里贴出全部代码吧
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 { }
有备注的话我就不解释什么了,就是模块导入而已
接下来,在我们的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