简体   繁体   中英

Angular, Socket.io : Emit an array of object

With Angular how can I subscribe to an array of objects like this one:

[
    'abc/user2': { room: 'abc/user2', user: 'user2' },
    'abc/admin': { room: 'abc/admin', user: 'admin' }
]

Currently this doesn't work :

this.socketService.onRoom().subscribe(rooms => {
    this.rooms = rooms;
});

With socketService :

public onRoom() {
    return new Observable<any>(observer => {
        this.socket.on('room', (data: any) => observer.next(data));
    });
}

Edit:

Mybad, it seems that problem comes from the server (NodeJS/express/socket.io) :

chat-server.ts :

public rooms: Array<{room: string, user:string}> = [];

(...)
this.rooms[room] = {room: room, user: socket.user};
this.io.emit('room', this.rooms)
console.log('[server]rooms :', this.rooms)

Server side, console.log print :

[
    'abc/user2': { room: 'abc/user2', user: 'user2' },
    'abc/admin': { room: 'abc/admin', user: 'admin' }
]

But clientside in socketService , if i do a console.log(data) here :

public onRoom() {
    return new Observable<any>(observer => {
        this.socket.on('room', (data: any) => {
            console.log(data)
            observer.next(data)
        });
    });
}

It return :

[]

But if I emit serverside:

this.io.emit('room', Object.keys(this.rooms))

Clientside it return:

['abc/user2', 'abc/admin']

It's look like i can't emit an array of object from socket.io ?

You can't. You have to turn it into an observable of some kind..

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

export class AppComponent implements OnInit {

    private readonly data = [
        {
            'abc/user2': { room: 'abc/user2', user: 'user2' }
        },
        {
            'abc/admin': { room: 'abc/admin', user: 'admin' }
        }
    ];
    private data$;

    ngOnInit() {
        this.data$ = new Observable((observer) => {
            observer.next(this.data);
            observer.complete();
        });
    this.data$.subscribe(data => {
        console.log(data);
    });
}

Though there are many other ways (and probably better ways) to do it. Just an example for you since I don't know exactly what you are trying to accomplish.

You should create observable which you want to return outside of socket.on method.

public onRoom(): Observable<any> {
    BehaviorSubject<any> toReturn = new BehaviorSubject();
    this.socket.on('room', (data: any) => toReturn.next(data));
    return toReturn;
}
private myArray = [
    'abc/user2': { room: 'abc/user2', user: 'user2' },
    'abc/admin': { room: 'abc/admin', user: 'admin' }
];
private myObservable= Observable.of(this.myArray);

You can subscribe to myObservable then.

I finally manage to resolve this problem by not emitting an array of object, but just an object

chat-server.ts

//public rooms: Array<{room: string, user:string}> = [];
public rooms: any = {};

And client side, i convert my object to an array, so that i can iterate throw it in template.

chat-list.component.ts

this.socketService.onRoom().subscribe(rooms => {
    this.rooms = rooms;
    this.roomsArr = Object.entries(this.rooms);

});

Still, I don't understand why i couldn't manage to emit an array of object from socket.io

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM