JerryMissTom / ionic3-handbook

手摸手带你入门ionic3
34 stars 9 forks source link

10、网络请求 #10

Open JerryMissTom opened 6 years ago

JerryMissTom commented 6 years ago

大多数App不是简单的只使用本地数据,通常还会与服务器进行交互,这个时候就要用到网络请求的功能了。ionic的网络请求其实就是用的是Angular的。下面就结合豆瓣API的例子,对这个功能讲解下,然后根据实际项目的规范对其进行封装。

在根目录下,使用ionic generate page net创建一个新界面。然后在主页添加按钮,跳转到此界面。相关代码如下:

home.html
...
<button  class="btn-primary"  (click)="toNetPage()">跳转到网络请求界面</button>
horm.ts
...
toNetPage(){
    this.navCtrl.push('NetPage');
}

网络请求的功能在单独的模块中,我们需要先在AppModule中导入,代码如下:

app.modules.ts

import { HttpClientModule } from '@angular/common/http';

imports: [
    HttpClientModule,
    ...
  ]

紧接着我们才使用,具体代码见net.ts:

net.ts

import {HttpClient,HttpHeaders} from '@angular/common/http';
import 'rxjs/add/operator/timeout';

...
export class NetPage {

  constructor(private http : HttpClient) {}

  ionViewDidLoad() {
    this.http.get('https://api.douban.com/v2/movie/in_theaters?start=0&count=1')
      .timeout(10000)  // 10秒无反应则报错
      .subscribe(success => {
          console.log(success);
      }, fail => {
          console.log('请求失败');
      });
  }
}

通过ionic serve命令运行项目,在首页点击进入网络请求页,在Console中你会发现如下图所示的错误。

2

有经验的人一下子就看出是跨域问题,跨域问题的解决方案很多,这里就不一一提及,典型的就是使用代理,我这儿为了方便是关闭Chrome浏览器的安全策略,从而使其支持跨域请求,Mac OS上关闭安全策略的命令如下:

open -n /Applications/Google\ Chrome.app/ --args --disable-web-security  --user-data-dir=/Users/你的自己的用户名/MyChromeDevUserData/

在终端中运行会新出现一个Chrome浏览器,输入localhost:8100访问我们的已经运行的项目,从首页进入网络请求页,返回的数据如图所示。

1

封装

通常我们的网络请求有自己的请求头等东西,每个网络请求的界面都写一次太麻烦了,所以自然而然就想到了对网络请求进行封装,这儿provider就该上场了。 在项目根目录下运行ionic generate provider http,最后的目录结构如下:

── app
├── assets
├── components
├── index.html
├── manifest.json
├── pages
├── providers
│   └── http
│       └── http.ts

除此之外,还会在app.module.ts中自动添加如下代码:

app.modules.ts

import { HttpProvider } from '../providers/http/http';

 providers: [
    HttpProvider
 ]

之前提到过provider其实就是Angular中的service,只是换了个名字,它的用法涉及到依赖注入的概念,代码中会有@Injectable()这个装饰器,更多的内容需要大家自己去学习。这里只强调一点,创建一个provider文件,都要在app.module.tsproviders中引入,不然会报错。

接着将我们网络请求的代码写在里面,如下:

http.ts

import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/timeout';

@Injectable()
export class HttpProvider {

  constructor(public http : HttpClient) {}

// get请求
   get(url) {
    return this.http.get(url).timeout(10000).catch(this.handlerError);
  }

 // post请求,request是请求参数组成的Object
   post(url, request) {
    const body : string = JSON.stringify(request);
    const httpOptions = {
      headers: new HttpHeaders({'Content-Type': 'application/json'})
    };
    return this.http.post(url, body, httpOptions).timeout(10000).catch(this.handlerError);
  }

  private handlerError(error : Response | any) {
    const body = error.json() || {};
    return Observable.throw(body);
  }
}

用法如下:

net.ts
...
import {HttpProvider} from '../../providers/http/http';

export class NetPage {

  constructor(private http : HttpProvider) {}

  ionViewDidLoad() {
    this.http.get('https://api.douban.com/v2/movie/in_theaters?start=0&count=5')
      .subscribe(success => {
        console.log(success)
      }, fail => {
        console.log('网络错误');
      });
  }
}

我在项目代码里还写了个post请求的例子,大家可以查看下。

farashraid commented 5 years ago

感谢您的教程!非常简洁明了~

JerryMissTom commented 5 years ago

@farashraid 惭愧啦,之前写的,里面还有很多不足,需要更正的。