WeSocket通訊
- WeSocket協(xié)議:低負(fù)載二進(jìn)制協(xié)議,允許在同一個(gè)連接中同時(shí)雙方向的數(shù)據(jù)傳遞,在發(fā)送請(qǐng)求的同時(shí)還能接受數(shù)據(jù),所以WeSocket協(xié)議通訊時(shí)延遲低,而且由于常連接的存在,不需要每次請(qǐng)求時(shí)都需要攜帶一些連接相關(guān)的信息
http協(xié)議進(jìn)行通訊時(shí),客戶(hù)端和服務(wù)器的連接在同一時(shí)間只能有一個(gè)發(fā)送請(qǐng)求和服務(wù)器響應(yīng)不能同時(shí)進(jìn)行 - 安裝WeSocket依賴(lài)庫(kù)和類(lèi)型定義文件
npm i ws --save
npm i @types/ws --save-dev
- 在8085端口創(chuàng)建一個(gè)服務(wù)器,當(dāng)有客戶(hù)端連接到這個(gè)服務(wù)器時(shí)給這個(gè)客戶(hù)端推送一個(gè)消息
import {Server} from 'ws'
const wsServer =new Server({port:8085});
wsServer.on("connection",websocket=>{
websocket.send("服務(wù)器主動(dòng)推送消息");
websocket.on("message",message=>{
console.log("接收"+message);
})
});
- 在需要連接的客戶(hù)端中生成一個(gè)service
ng g service shared/webSocket
export class WebSocketService {
ws:WebSocket;
constructor() { }
createObservableSocket(url:string):Observable<any>{
this.ws=new WebSocket(url);
return new Observable(
observer=>{
this.ws.onmessage=(event)=>observer.next(event.data);
this.ws.onerror=(event)=>observer.error(event);
this.ws.onclose=(event)=>observer.complete();
}
);
}
sendMessage(message:string){
this.ws.send(message);
}
}
export class WebSocketComponent implements OnInit {
constructor(private wsService:WebSocketService) { }
ngOnInit() {
this.wsService.createObservableSocket("ws://localhost:8085")
.subscribe(
data=>console.log(data),
err=>console.log(err),
()=>console.log("流已經(jīng)結(jié)束")
);
}
sendMessageToserver(){
this.wsService.sendMessage("hello from client");
}
}
- 定時(shí)向所有客戶(hù)端推送消息
setInterval(()=>{
if(wsServer.clients){
wsServer.clients.forEach(client=>{
client.send("定時(shí)推送");
})
}
},2000);
從服務(wù)器將數(shù)據(jù)傳輸?shù)娇蛻?hù)端使用
- 將商品服務(wù)中的商品數(shù)組和評(píng)論數(shù)組放入到node服務(wù)器中,從服務(wù)器中獲取數(shù)據(jù),將方法中的商品數(shù)組,和評(píng)論數(shù)組使用一個(gè)流Observable來(lái)引用
getProducts(): Observable<Product[]> {
return this.http.get("/api/products").map(res=>res.json());
}
getProduct(id:number): Observable<Product> {
return this.http.get("/api/product"+id).map(res=>res.json());
}
getCommentsForProductId(id: number):Observable<Comment[]> {
return this.http.get("/api/product"+id+"/comments").map(res=>res.json());
}
- 在商品組件中同樣執(zhí)行相同的操作使用Observable,并且在模板中將管道過(guò)濾器改為使用異步管道async
<div class="col-md-4 col-sm-4 col-lg-4" *ngFor="let product of products | async">
- 在商品詳情組件中將服務(wù)器獲取的兩個(gè)數(shù)組的流轉(zhuǎn)化成數(shù)組以便使用
ngOnInit() {
let productId:number = this.routeInfo.snapshot.params["productId"];
this.productService.getProduct(productId).subscribe(
product=>this.product=product
);
this.productService.getCommentsForProductId(productId).subscribe(
comments=>this.comments=comments
)
}
- 在界面中有屬性不能讀取,說(shuō)明有數(shù)據(jù)屬于undefined,因?yàn)楝F(xiàn)在的服務(wù)都是通過(guò)http,這就是一個(gè)異步服務(wù),在組件中還沒(méi)有獲取到數(shù)據(jù)時(shí)就屬于undefined需要將模板中的product和comment后加上?,但是for循環(huán)中的comment不需要更改,因?yàn)閚gFor是會(huì)自動(dòng)檢測(cè)數(shù)據(jù)是否為空,這樣就完成了數(shù)據(jù)從服務(wù)器到客戶(hù)端的傳輸
<div class="thumbnail">
<img src="http://placehold.it/820x230" >
<div>
<h4 class="pull-right">{{product?.price}}元</h4>
<h4>{{product?.title}}</h4>
<p>{{product?.desc}}</p>
</div>
<div>
<p class="pull-right">評(píng)論 {{comments?.length}} 條</p>
<p>
<app-start [rating]="product?.rating" ></app-start>
</p>
</div>
</div>
<div class="well">
<div>
<button class="btn btn-success" (click)="isCommentHidden=!isCommentHidden">評(píng)論</button>
</div>
<div [hidden]="isCommentHidden">
<div><app-start [(rating)]="newRating" [readonly]="false"></app-start></div>
<div>
<textarea [(ngModel)]="newComment"></textarea>
</div>
<button class="btn" (click)="addComment()">發(fā)表</button>
</div>
<div class="row" *ngFor="let comment of comments">
<hr>
<div>
<div class="col-md-12">
<app-start [rating]="comment?.rating"></app-start>
<span>用戶(hù)名:{{comment.user}}</span>
<span class="pull-right">{{comment.timestamp}}</span>
<p></p>
<p>
{{comment.content}}
</p>
</div>
</div>
</div>
</div>