简介
- 在
JavaScript
中通常有三种处理异步代码的方式。回调(callback),承诺(Promise),可观察对象(observable)。 http
在Angular
中被拆分为一个单独的模块,因此需要从Angular
中导入一些常量。
import { Http, Response, RequestOption, Headers} from '@angular/http'
- 在
app.ts
中需要导入HttpModule
模块。
import { HttpModule} from '@angular/http';
@NgModule({
declarations:[],
imports:[HttpModule],
bootStrap: [HttpApp],
providers: []
})
- 把服务注入组件中
class MyFooComponent {
constructor(public http: Http){
makeRequest(): void{
}
}
}
基本请求
1.首先导入一些模块,然后指定@Component的selector。
import { Http , Response } from '@angular/http';
import {Component} from '@angular/http';
@Component({
selector: 'simple-http',
})
- 构建视图
template:`
<h2>Basic Request</h2>
<button type="button" (click)="makeRequest()">make request</button>
<div *ngIf="loading..."></div>
<pre>{{data | json}}</pre>
`
- 构建控制器
export class SimpleHttpComponent{
data :Object;
loading: boolean;
constructor(
private http : Http
){}
makeRequest() : void{
this.loading= true;
this.http.request('http://jsonplaceholder.typicode.com/postts/1')
.subscribe((res: Response)=>{
this.data = res.json();
this.loading =false;
})
}
}
-
当我们调用
makeRequest
时,首先要设置this.loading= true
。这会在页面上显示云载入指示器。 -
发
http
请求的方式:调用this.http.request
并传入URL作为GET请求的参数。http.request
会返回一个Observable
对象,可以使用subscribe
订阅变化。 -
当
http.request
从服务器返回一个流时,它就会发出一个Response
对象。我们用json
方法提取出响应体并解析成一个Object
,然后将这个Object
赋值给this.data
。 -
只要我们得到了响应,就不需要加载任何东西了,所心就需要设置
this.loading=false
。
编写YouTubeSearchComponent
- 编写
SearchResult
,用obj?: any
来模拟关键词参数。在构造ideoUrl
时使用了硬编码。
class SearchResult {
id : string;
title : string;
description : string;
thumbnailUrl: string;
videoUrl: string;
consturctor(obj?: any){
this.id = obj && obj.id || null;
this.title = obj && obj.title || null;
this.description = obj && obj.description || null;
this.thumbnailUrl = obj && obj.thumbnailUrl || null;
this.videoUrl = obj && obj.videoUrl || `https://www.youtube.com/watch?v=${this.id}`;
}
}
- 编写
YouTubeService
为YouTubeService
设置两个用来表示API
密钥和API URL
的常量
let YOUTUBE_API_KEY: string ="XXXXX";
let YOUTUBE_API_URL :string = "https://www.googleapis.com/youtube/v3/search";
为了解决环境配置问题,注入这些常量
我们要获取http.get
的返回值,并用map来从请求中获取Response
,这里使用.json()从response
中提取返回体并同时实例化成一个对象,然后遍历每个项目并将其转换成一个SearchResult
。
(<any>response.json()).items
是告诉ts,我们并不想在这里进行严格的类型检查,因为当我们使用JSON API
时通常并没有API
响应体的类型定义信息,所以ts
不知道返回的object
中会有一个items键,编译器就会出错。
export var youTbueServicrInjectables: Array<any> =[ {provide: YouTubeService, useClass: YouTbueService}, {provide: YOUTUBE_API_KEY, useClass: YOUTUBE_API_KEY}, {provide: YOUTUBE_API_URL, useClass: YOUTUBE_API_URL}]@Injectable()export class YouBubeService{ constructor( private http: Http, @Injectable(YOUTUBE_API_KEY) private apiKey: string, @Injectable(YOUTUBE_API_URL) private apiUrl: stirng ){} search(query: string):Observable<SearchResult[]>{ let params: string =[ `q=${query}`, `key=${this.apiKey}`, `part=snippet`, `maxRseutls=10` ].join('&'); let queryUrl:string =`${this.apiUrl}?${params}`; return this.http.get(queryurl).map((response :Response)=>[ return (<any>response.json()).items.map(item=>{ return new SearchResult({ id: item.id.videoId, title: item.snippet.title, desciption: item.snippet.description, thumbnailUrl: item.snippet.thumbnails.high.url }) }) ]) }}
在app.ts
中使用
import { HttpModule} from "@angular/http";import { youTubeServiceInJectables} from "components/YouTubeSearchComponent";@NgModule({ declarations: [ HttpApp ], imports:[ BrowserModule, HttpModule], providers:[ youTubeServiceInJectables]})class HttpAppModule{}
-
编写
SearchBox
我们通过
implements oninit
让这个类实现对应的接口,这么做是因为需要使用生命周期中的ngOninit
的回调,如果一个类声明implements oninit
,那么ngOninit
函数会在首次变化检查后调用。
@Component({ outputs:['loading', 'result'], selector:'search-box', template:` <input type="text" class="form-control" placeholder="Search" autofocus>`})export class SearchBox implements Oninit{ loading: EventEmitter<boolean> = new EventEmitter <boolean>(); results: EventEmitter<SearchResult[]>=new EventEmitter<SearchResult[]>(); constructor( private youtube: YouTubeService, private el : ElementRef, ){} ngOninit():void{ Obesrvable.fromEvent(this.el.nativeElement,'keyUP') .map((e:any)=>e.target.value .filter((text:string)=>text.length>1) .debounceTime(250) .do(()=>this.loading.next(true)) .map((query:string)=>this.youtube.search(query)). .switch() .subscribe( (results: SearchResult[])=>{ this.loading.next(false); this.results.next(results); }, (err:any)=>{ this.loading.next(false); }, ()=>{ this.loading.next(false); } ) ) }}
<search-box (loading)="loading=$event" (results)="updateResults($event)" ></search-box>
- 发送
post
请求
makepost(): void{ this.loading=true; this.http.post( 'http://jsonplaceholder.typicode.com/posts', JSON.stringfy({ body: 'bar', title: 'foo', userId: 1}) ) .subscribe((res: Response)=>{ this.data=res.json(); this.loading=false; })}
- 发送
delete
请求
makeDelet():void{ this.loading=true; this.http.delete( 'http://jsonplaceholder.typicode.com/posts/1' ) .subscribe((res:Response)=>{ this.data=res.json; this.loading= false; })}
- 携带可选的末位参数
makeHeaders():void{ let headers: Headers =new Headers(); headers.append('X-API-TOKEN', 'ng-book'); let opts: RequestOptions = new RequestOptions(); opts.headers=headers; this.http.get( 'http://jsonplaceholder.typicode.com/posts/1', opts) .subscribe((res: Response)=>{ this.data =res.json(); })}