【问题标题】:How to use socket.io in angular with node.js?如何在 node.js 中以角度使用 socket.io?
【发布时间】:2019-03-05 02:44:39
【问题描述】:

客户端我使用 Angular 6,服务器端我使用 node.js。

在 Angular 6 控制台中,它打印消息并 socket.io id({message: "Hello World", id: "6An-ctwlwbZZWrfMAAAB"}) 使用下面的代码后。

此代码是正确的或此代码有任何更改,因为我不确定此代码是否有助于纠正此问题。

另一个问题是我的项目中有超过 15 个组件,那么如何将这个socket.io 用于所有组件,或者我必须在所有其他组件中导入这个app.component.ts 代码。

app.js(服务器端)

after installing (npm i socket.io)

const express = require('express');
var app = express();
const http = require('http');
const socketIo = require('socket.io');
const server = http.Server(app);
const io = socketIo(server);

server.listen(3000,function(req,res){
  console.log("listen at 3000!");
});

io.on('connection',(socket) => {
  socket.emit('hello',{
    message : 'Hello World',id: socket.id
  })
});

app.component.ts(客户端)

after installing (npm i socket.io)

import * as socketIo from 'socket.io-client';

export class AppComponent implements OnInit {
  ngOnInit(){
    const socket = socketIo('http://localhost:3000/');
      socket.on('hello',(data) => console.log(data));
    }
  }
}

【问题讨论】:

  • 检查这个:blog.codewithdan.com/…
  • 你有什么错误吗?
  • 不,我没有像这样在 crome 浏览器中收到任何错误控制台打印 ({message: "Hello World", id: "6An-ctwlwbZZWrfMAAAAB"}) 但我有超过 15 个组件所以我不知道如何使用所有组件通用的 socket.io,你告诉我为此提供服务,但使用服务如何获取所有组件的 socket.io 角度到节点
  • 你能试试我的示例代码吗
  • 我正在尝试,我不知道从 '../shared/interfaces' 的服务导入 { Socket } 中这是什么;

标签: node.js angular socket.io


【解决方案1】:

实现此机制的一种方法是使用ngx-socket-io,在模块级别或根级别连接您的节点服务器,如下所示

app.module.ts 代码

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
import { AppComponent } from './app.component';
const config: SocketIoConfig = { url: 'http://192.168.1.187:9301', options: {}  };
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SocketIoModule.forRoot(config),
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

创建一项服务来处理您的传入和传出流量。

import { Injectable } from '@angular/core';
import { Socket } from 'ngx-socket-io';
@Injectable({
  providedIn: 'root'
})
export class SocketService {

  constructor(public socket: Socket) { }
  getMessage() {
    return this.socket
        .fromEvent<any>('msg')
        .map(data => data.msg);
}

sendMessage(msg: string) {
    this.socket.emit('msg', msg);
}
}

更新组件文件中的代码

export class AppComponent implements OnInit {
  constructor(private socketService: SocketService) {}
  title = 'app';
  incomingmsg = [];
  msg = 'First Protocol';
  ngOnInit() {
    this.socketService
        .getMessage()
        .subscribe(msg => {
          console.log('Incoming msg', msg);
        });
        this.sendMsg(this.msg);
  }
  sendMsg(msg) {
    console.log('sdsd', msg);
    this.socketService.sendMessage(msg);
 }
}

【讨论】:

  • getMessage() { return this.socket .fromEvent('msg') .map(data => data.msg); } 这给了我 .map 中的错误
  • 你使用的是什么版本的角度?
  • 我正在使用 Angular 7
  • 本例中如何添加不记名令牌?配置在appmodule中,但是bearer稍后可以在其他模块中使用,如何将其添加到每个请求中。
【解决方案2】:

创建服务并将您的套接字数据转换为 Observable 流

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/behaviorSubject';  
import { Observer } from 'rxjs/Observer';
import { Observable } from 'rxjs/Observable';
import * as Rx from 'rxjs';
import * as io from 'socket.io-client';

@Injectable()
export class ChatService {

  observable: Observable<string>;
  socket;

  constructor() {
    this.socket = io('http://localhost:3000');     
   }

   getData(): Observable<string> {
    return this.observable = new Observable((observer) => 
      this.socket.on('hello', (data) => observer.next(data))
    );
  }

  // This one is for send data from angular to node 
  pushData(e) {
    this.socket.emit('hello', e);
  }
}

然后从组件调用

App.component.ts

import { Component } from '@angular/core';
import { ChatService } from './common/chat.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {  
  title;
  chat;
  constructor(private cService: ChatService) {
    this.cService.getData().subscribe(data => console.log(data));
  }

  onClick(e: string) {
    this.cService.pushData(e);
    this.chat = '';
  }
}

【讨论】:

    【解决方案3】:

    您可以创建一个使用套接字的服务。例如(当然这是一个非常简单的例子):

    /* e.g app/shared/io/io.service.ts */
    
    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs/Observable';
    
    import * as socketIo from 'socket.io-client';
    
    const SERVER_URL = '/';
    
    /** Your events enum */
    export enum IOEventName {
        EVENT_NAME_1 = "EVENT_NAME_1",
        EVENT_NAME_2 = "EVENT_NAME_2",
        ...
    }
    
    /** Interfaces for your event messages */
    export interface IEventName1Message {
        propOne: number,
        propTwo: string,
        ...
    }
    
    export interface IEventName2Message {
        propOne: Date,
        propTwo: Boolean,
        ...
    }
    ...
    
    @Injectable()
    export class SocketService {
        private socket: SocketIOClient.Socket;
    
        public initSocket(): void {
            this.socket = socketIo(SERVER_URL);
        }
    
        public onEvent<T>(event: IOEventName): Observable<T | Array<T>> {
            return new Observable<T>(observer => {
                this.socket.on(event, (data: T) => observer.next(data));
            });
        }
    
        public destroy() {
            if (this.socket) {
                this.socket.removeAllListeners();
                this.socket.close();
                this.socket = undefined;
            }
        }
    }
    

    并在任何组件中使用它:

    import { SocketService, IOEventName, IEventName1Message, IEventName2Message } 
        from 'app/shared/io/io.service';
    
    export class AppComponent implements OnInit, OnDestroy {
        constructor(private socketService: SocketService) { }
    
        ngOnInit() {
            this.socketService.initSocket();
            this.socketService
                .onEvent<IEventName1Message>(IOEventName.EVENT_NAME_1)
                .subscribe(data => { /* message received */ });
    
            this.socketService
                .onEvent<IEventName2Message>(IOEventName.EVENT_NAME_2)
                .subscribe(data => { /* message received */ });
        }
    
        ngOnDestroy() {
            this.socketService.destroy();
        }
    }
    

    【讨论】:

    • 从 'app/shared/io/io.service' 导入 { SocketService, IOEventName, IEventName1Message, IEventName2Message };如何导入这个?我的 node.js 代码是对的吗?
    • @AmishaRana app/shared/io/io.service 是我示例的第一个代码块。是角码。
    • 这个例子很好,但可以改进。为什么每次在“onEvent”函数中返回一个新的 Observable ?由于此功能可以被许多组件使用。您应该只通过 IOEventName 创建一个。 initSocket 不是很好,initSocket 应该是服务构造器。您不应该为同一个 url 打开两个套接字。
    • @xrobert35 你是对的。这是一个简单的例子,可以改进。
    猜你喜欢
    • 2023-03-10
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多