KhoPhi
KhoPhi

Reputation: 9537

socket.io client Angular Cannot read property 'emit' of undefined

I have this component in Angular

import { Component, OnInit} from "@angular/core";
import * as io from "socket.io-client";
import { environment } from "src/environments/environment";

@Component({
  selector: "app-home",
  templateUrl: "./home.component.html",
  styleUrls: ["./home.component.css"]
})
export class HomeComponent implements OnInit {
  busy: boolean;
  username: string;
  socket: any;
  user = JSON.parse(localStorage.getItem("user"));
  token = localStorage.getItem("token");

  constructor() {
    // THIS WORKS
    this.socket = io.connect(environment.endpoint, {
      query: `username=${this.user.username}&token=${this.token}`
    });
  }

  ngOnInit() {
    this.socket.on("client-retrieve", function(data) { // <--- THIS WORKS
      console.log(data);
      this.socket.emit( // <---------- THIS FAILS, throws the error
        "request-response",
        {
          from: this.user.username,
          to: data.from,
          command: "SEND",
          payload: [{ 'something': "something" }]
        },
        (err, message) => {
          console.log(err);
          console.log(message);
        }
      );
    });
  }

  onSubmit(formData) {
    console.log("FormData: ", formData);
    this.socket.emit( // This works. Gets triggered by a form submit
      "request-forward",
      {
        command: "PULL",
        from: this.user.username,
        to: formData.username
      },
      (err, message) => {
        console.log(err);
        console.log(message);
      }
    );
  }
}

The error thrown is basically: core.js:5828 ERROR TypeError: Cannot read property 'emit' of undefined. at Socket.<anonymous> (home.component.ts:26)

What am I doing wrong? Because calling emit via the onSubmit(...) works.

Upvotes: 0

Views: 376

Answers (1)

Damian C
Damian C

Reputation: 2171

You'll want to change it to an arrow function so this will reference the lexical context and not the caller context.

On this line:

this.socket.on("client-retrieve", function(data) { // <--- THIS WORKS

Change to this:

 this.socket.on("client-retrieve", (data) => { // <--- THIS WORKS

Your method should now look like:

  ngOnInit() {
    this.socket.on("client-retrieve", (data) => { // <--- THIS WORKS
      console.log(data);
      this.socket.emit( // <---------- THIS FAILS, throws the error
        "request-response",
        {
          from: this.user.username,
          to: data.from,
          command: "SEND",
          payload: [{ 'something': "something" }]
        },
        (err, message) => {
          console.log(err);
          console.log(message);
        }
      );
    });
  }

https://www.typescriptlang.org/docs/handbook/functions.html#this-and-arrow-functions

Upvotes: 1

Related Questions