Angular WebSocket代码详解

WebsocketService代码

import { Injectable } from '@angular/core';
import * as Rx from "rxjs/Rx";

@Injectable({
  providedIn: 'root'
})
export class WebsocketService {
  constructor() { }
  private subject: Rx.Subject<MessageEvent>;

  public connect(url): Rx.Subject<MessageEvent> {
    if (!this.subject) {
      this.subject = this.create(url);
      console.log("Successfully connected: " + url);
    }
    return this.subject;
  }

  private create(url): Rx.Subject<MessageEvent> {
    let ws = new WebSocket(url);      
    let observable = Rx.Observable.create((obs: Rx.Observer<MessageEvent>) => {
      ws.onmessage = obs.next.bind(obs);
      ws.onerror = obs.error.bind(obs);
      ws.onclose = obs.complete.bind(obs);
      return ws.close.bind(ws);
    });
    let observer = {
      next: (data: string) => {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(data);
        }
      }
    };
    const innerSubject = new Rx.Subject();//为了能够多次订阅,用subject对observable进行封装
    observable.subscribe(data => {
      innerSubject.next(data)
    });
    return Rx.Subject.create(observer, innerSubject);
  }
}

解释

使用Rxjs的Websocket库能让你在多个地方接收或发送消息:

  1. ws.onmessage = obs.next.bind(obs); 该句的意思是,当接收websocket发送的消息时,调用observer对象的next方法。用bind保证对象的this指针始终为observer对象。
  2. return Rx.Subject.create(observer, innerSubject);这句返回的是一个Subject对象,因为web socket的onmessage的参数是一个MessageEvent对象,所以这句返回的是Subject. 当外部订阅该返回对象后,在接收到websocket的onmessage消息后,observable 的next函数将发送onmessage函数的传入值,订阅对象就可以接收到。
  3. 为什么用innerSubject 对observable进行封装,因为observable只能订阅一次,而subject可以订阅多次,这样我们可以在不同的地方订阅,都可以接收到websocket消息。

ChatService代码

import { Injectable } from '@angular/core';
import { Subject } from "rxjs/Rx";
import { WebsocketService } from "./websocket.service";
import { AuthService } from 'src/app/core/auth.service';

const CHAT_URL = "ws://localhost:5000/ws/";

@Injectable({
  providedIn: 'root'
})
export class ChatService {
  public messages: Subject<string>;
  constructor(wsService: WebsocketService, authService:AuthService) { 
    let authHeader = authService.getAuthorizationHeader() || "?";
    var url = CHAT_URL + "?token=" + authHeader;
    this.messages = <Subject<string>>wsService.connect(url).map(
      (response: MessageEvent): string => {
        console.log(response.data);
        return response.data;
      }
    );
  }

  subscribeMessage() {
    this.messages.subscribe(msg => {
      console.log("Response from websocket: " + msg);
    });
  }

  sendMessage(message) {
    this.messages.next(message);
  }
}

解释

  1. messages: Subject,我们用web socket发送接收Json字符串,所以这里的Subject的泛型对象是字符串。
  2. this.messages = <Subject>wsService.connect(url).map(
    (response: MessageEvent): string => {.这里web socket的onmessage返回的是MessageEvent对象,这里用map函数吧Subject转换成为Subject.即我们的msaages对象。
  3. subscribeMessage() .当web socket的onmessage方法被调用后,websocketService中的Subject对象的next方法将发射MessageEvent对象,经过map转换后成为字符串对象,这里就是订阅到这个字符串。
  4. sendMessage(message),这里messages对象发送next消息就是调用WebsocketService中的observer的next,即next: (data: string) => {
    if (ws.readyState === WebSocket.OPEN) {
    ws.send(data); } }
    先判断ws是否是打开状态,然后发送数据到服务器端。

调用

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ChatService } from '../service/chat.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {  
  constructor(private router: Router, 
    private chatService: ChatService) {
  };

  ngOnInit() {
    this.chatService.subscribeMessage();//多个调用将接收多次。
  }

  sendMsg() {
    this.chatService.sendMessage("test");
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值