建立web伺服器
使用express搭建
- 通過npm init -y 指令會建立一個含有預設配置的 package.json的檔案
- 為了讓nodejs支援typescript 使用指令:npm i @types/node —save
- 建立tsconfig.json檔案:
{ "compilerOptions": { "target": "es5", "module": "commonjs", "emitDecoratorMetadata": true, "experimentalDecorators": true, "outDir": "build", "lib": ["es6"] }, "exclude": ["node_modules"] }
- 然後安裝express相關插件 npm install express —save
- 同樣需要讓他支援typescript npm i @types/express —save
- 編譯過後(我使用的是VS code, 通過run task,進行編譯), 通過 node build/編譯出來的檔案。執行就行。執行指令為node build/auction_server.js
- 如果需要熱部署可以安裝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搭建
- 通過指令安裝 npm install express-generator —save -g
- 下載下傳好後,直接express 項目名 即可。
- 然後通過指令 npm install 安裝相應的包
- 如果想運作 通過指令 npm start。
Http通訊
要想使用angular的http請求,請按照如下幾步操作來做:
- 在app.module.ts imports中添加上HttpClientModule子產品
import { HttpClientModule } from '@angular/common/http';
- 在需要使用的地方,引入Obserable,和HttpClient包
import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http';
- 将HttpClient依賴注入進來,然後定義我們想要的請求:
constructor(private http: HttpClient) { this.dataObservable = http.get('api/product'); }
- 然後在想要發送請求的地方,直接訂閱我們剛剛定義的那個請求:
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伺服器的搭建特别類似:
- 引入WebSocket包
//引入WebSocket的包 import {Server} from 'ws'
- 監聽WebSocket連接配接時間,然後作出對應的處理
webSocket.on('connection', websocket => { //從伺服器端推送一個消息傳回給用戶端 websocket.send("用戶端連接配接後,響應給用戶端的消息"); //接收從用戶端端發來的消息 websocket.on('message', message => console.log(message)); });
- 有的時候我們也有伺服器端在一段時間間隔内,不斷向用戶端推送的需要:
** * 定時向用戶端推送消息,間隔為三秒 */ setInterval(function(){ if (webSocket.clients) { webSocket.clients.forEach(client => { client.send('定時發送消息'); }); } }, 3000);
用戶端websocket
封裝兩個方法用于以後的使用:
首先定義一個變量
ws: WebSocket;
- 建立與伺服器端的連接配接
/** * 這個方法用于當我們發送一個連接配接的方法 * @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(); }); }
- 向伺服器端推送消息
/** * 通過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('從用戶端發送的消息');