天天看點

Angular4總結(七)—— 與伺服器通信

建立web伺服器

使用express搭建
  1. 通過npm init -y 指令會建立一個含有預設配置的 package.json的檔案
  2. 為了讓nodejs支援typescript 使用指令:npm i @types/node —save
  3. 建立tsconfig.json檔案:
    {
        "compilerOptions": {
            "target": "es5",
            "module": "commonjs",
            "emitDecoratorMetadata": true,
            "experimentalDecorators": true,
            "outDir": "build",
            "lib": ["es6"]
    
        },
        "exclude": ["node_modules"]
    }           
  4. 然後安裝express相關插件 npm install express —save
  5. 同樣需要讓他支援typescript npm i @types/express —save
  6. 編譯過後(我使用的是VS code, 通過run task,進行編譯), 通過 node build/編譯出來的檔案。執行就行。執行指令為node build/auction_server.js
  7. 如果需要熱部署可以安裝nodemon 指令為 npm install nodemon -g

下面貼出伺服器端代碼的樣例:

//引入Express包的相關引用
import * as express from 'express'

//引入WebSocket的包
import {Server} from 'ws'
import bodyParser = require('body-parser');

/**
 * 通過express對象,拿到具體屬性
 */
const app = express();
//如果需要post請求,一定要加入這段代碼,否則會request body會是undefined
app.use(bodyParser.json());

/**
 * 這個類作為一個 product的實體類,被用來承接從背景發過來的資料。
 */
// tslint:disable-next-line: class-name
export class productModel {
    constructor(
      public id: number,
      public title: string,
      public price: number,
      public rating: number,
      public desc: string,
      public categories: Array<string>
    ) {}
  }
  
  const products: productModel[] = [ 
    new productModel(1,"title1",1,1,"Description1,Description1,Description1,Description1",["圖書","電子書"]),
    new productModel(2,"title2",2,2,"Description2,Description2,Description2,Description2",["手機","電子書"]),
    new productModel(3,"title2",2,3,"Description3,Description3,Description3,Description3",["pad","筆記本"]),
    new productModel(4,"title2",2,4,"Description4,Description4,Description4,Description4",["手機","筆記本"]),
    new productModel(5,"title2",2,5,"Description5,Description4,Description4,Description4",["筆記本","圖書"]),
    new productModel(6,"title6",6,5,"Description6,Description6,Description6,Description6",["pad","手機"])
  ];


  // tslint:disable-next-line: class-name
export class commentModel {
  constructor(
    public id: number,
    public productId: number,
    public title: string,
    public rating: number,
    public desc: string
  ) {}
}

 const comments: Array<commentModel> = [
  // tslint:disable-next-line: no-use-before-declare
  new commentModel(1, 1, "title1", 1, "Comment1"),
  // tslint:disable-next-line: no-use-before-declare
  new commentModel(2, 1, "title2", 2, "Comment2"),
  // tslint:disable-next-line: no-use-before-declare
  new commentModel(3, 1, "title3", 3, "Comment3"),
];

/**
 * 定義一個get請求的API
 */
app.get('/', (request, response) => {
    response.send('Hello Express');
});

/**
 * 定義一個get請求的API,為了擷取商品資訊。
 */
app.get('/api/product', (request, response) => {
    response.json(products);
});

app.get('/api/product/:id', (request, response) => {
    response.json(products.find((product) => product.id == request.params.id));
});

app.get('/api/comments', (request, response) => {
  response.json(comments);
});

app.get('/api/comments/:productId', (request, response) => {
  response.json(comments.filter(comment => comment.productId == request.params.productId));
});

app.post('/api/products/condition', (req, res) => {
  console.log(req.body);
  res.json(products);
});

/**
 * 讓伺服器監聽8000端口,并且開啟服務。
 */
app.listen(8000, 'localhost', () => {
    console.log('node js 伺服器已經啟動!!');
});
           
通過express-generator搭建
  1. 通過指令安裝 npm install express-generator —save -g
  2. 下載下傳好後,直接express 項目名 即可。
  3. 然後通過指令 npm install 安裝相應的包
  4. 如果想運作 通過指令 npm start。

Http通訊

要想使用angular的http請求,請按照如下幾步操作來做:

  1. 在app.module.ts imports中添加上HttpClientModule子產品
    import { HttpClientModule } from '@angular/common/http';           
  1. 在需要使用的地方,引入Obserable,和HttpClient包
    import { Observable } from 'rxjs';
    import { HttpClient } from '@angular/common/http';           
  2. 将HttpClient依賴注入進來,然後定義我們想要的請求:
    constructor(private http: HttpClient) {
        this.dataObservable = http.get('api/product');
       }           
  3. 然後在想要發送請求的地方,直接訂閱我們剛剛定義的那個請求:
    this.dataObservable.subscribe((response) => {
            console.log(response);
            this.products = response;
        });           

️請求是在這裡subscribe的時候,才會真正的發送出去。

下面給出完整的代碼:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {

  private dataObservable: Observable<any>;
  private products: Array<any>;

  constructor(private http: HttpClient) {
    this.dataObservable = http.get('api/product');
   }

  ngOnInit() {
    this.dataObservable.subscribe((response) => {
        console.log(response);
        this.products = response;
    });
  }

}
           

然後需要着重說一下的是,這樣雖然說定義好了,但是請求還是發不出去的,因為我們要通路的不可能是在當面的這個項目中的,一定是開在了别的某台機器上的某個項目裡。

那這應該怎麼辦呢?

我們需要定一個檔案,告訴angular這些情況,我們定義一個proxy.config.json,檔案内容如下:

{
    "/api": {
        "target": "http://localhost:8000"
    }
}           

這段代碼的意思是告訴angular如果是api字首的URL,我們應該去本地的8000端口中去尋找。

最後将package.json中的 scripts中的start指令改為如下的指令即可:

"start": "ng serve --proxy-config proxy.conf.json"           

WebSocket通訊

webSocket協定

傳統的Http協定,隻能是在發送請求狀态和接收響應狀态互相交換。而webSocket可以在一個連接配接點進行交換資料。

webSocket是一個長連接配接。

webSocket協定相對于http協定攜帶的資料更少。

安裝webSocket在nodejs中

通過指令:

npm install ws --save
npm install @types/ws --save           
服務端websocket

websocket的伺服器端和Http伺服器的搭建特别類似:

  1. 引入WebSocket包
    //引入WebSocket的包
    import {Server} from 'ws'           
  2. 監聽WebSocket連接配接時間,然後作出對應的處理
    webSocket.on('connection', websocket => {
      //從伺服器端推送一個消息傳回給用戶端
      websocket.send("用戶端連接配接後,響應給用戶端的消息");
      //接收從用戶端端發來的消息
      websocket.on('message', message => console.log(message));
    });           
  3. 有的時候我們也有伺服器端在一段時間間隔内,不斷向用戶端推送的需要:
    **
     * 定時向用戶端推送消息,間隔為三秒
     */
    setInterval(function(){
      if (webSocket.clients) {
        webSocket.clients.forEach(client => {
          client.send('定時發送消息');
        });
      }
    }, 3000);           
用戶端websocket

封裝兩個方法用于以後的使用:

首先定義一個變量

ws: WebSocket;

  1. 建立與伺服器端的連接配接
    /**
    * 這個方法用于當我們發送一個連接配接的方法
    * @param url
    */
      createObserableWebSocket(url: string): Observable<any> {
     this.ws = new WebSocket(url);
     return new Observable(
    obserer => {
      //當有消息發送過來時候的一個監聽。
      this.ws.onmessage = (event) => obserer.next(event.data);
      //當有錯誤的時候一個監聽。
      this.ws.onerror = (event) => obserer.error(event);
      //當結束的時候一個監聽。
      this.ws.onclose = (event) => obserer.complete();
     });
      }           
  1. 向伺服器端推送消息
    /**
    * 通過websocket發送消息
    */
      sendMessage(msg: string) {
     this.ws.send(msg);
      }           

然後就可以通過使用這兩個方法進行與websocket服務端的通信。

在需要建立websocket的地方寫如下的代碼,一般會寫在ngOnInit方法中,也就是說在元件剛開始建立的時候,就會建立連接配接:

this.wsService.createObserableWebSocket('ws://localhost:8085')
    .subscribe(
      data => console.log(data),
      error => console.log(error),
      () => console.log('連接配接完成')
    );           

如果需要發送消息,可以寫如下代碼:

this.wsService.sendMessage('從用戶端發送的消息');           

繼續閱讀