0

I'm trying to get data with socket.io with this code:

server.js:

io.sockets.on('connection', function (socket) {
    console.log('Un client est connecté !');
    retrieveDB((res) =>{
      socket.emit('dataSend', res);
    });
});

filesearch.component.ts:

import * as io from 'socket.io-client';
options = []
socket = io.connect('http://localhost:4200');

ngOnInit(){
    this.socket.on('dataSend', function(message) { 
            this.options = message; 
            alert(message); 
        });
    if(this.myControl.value !='') { 
      this.init = 1; 
      this.filteredOptions = this.myControl.valueChanges
      .pipe(
          startWith(''),
          map(val => this.filter(val))
        );
    } else {
      this.init = 0;
    } 
  }

 filter(val: string): string[] {
    if(this.init){
      return this.options.filter(option =>
        option.toLowerCase().includes(val.toLowerCase()));
    } else {
      return []
    }
  }

The ngOnInit() should retrieve the data with socket.on() and the 2nd part initialise an autocompletion (https://material.angular.io/components/autocomplete/overview) but I always have a value of options nul. I know that this code is wrong because socket.on works asynchronously but I don't find how to correct it.

I tried to change the code by doing this:

ngOnInit(){
    this.socket.on('dataSend', function(message) { 
            this.options = message; 
            alert(message); 
        });
  }

onClick(){
  if(this.myControl.value !='') { 
      this.init = 1; 
      this.filteredOptions = this.myControl.valueChanges
      .pipe(
          startWith(''),
          map(val => this.filter(val))
        );
    } else {
      this.init = 0;
    } 

With the onClick() running when I click on the searchbar. But I still got the same result. So i'm begining to think that the probleme is elsewhere on my code. alert(this.options) return the good value but that's all.

I also tried to create a Display Button to display the value of options when I click on it but I still don't have the right answer.

I also tried to create an asynchrone function with a callback in ngOnInit():

ngOnInit(){
    this.socket.on('dataSend', function(message) { 
        this.initialise(message, this.autocompletion()); 
    });
  }

initialise(message, callback){
    this.options = message;
    alert(message); 
    callback();
}

autocompletion(){
    if(this.myControl.value !='') { 
      this.init = 1; 
      this.filteredOptions = this.myControl.valueChanges
      .pipe(
      startWith(''),
      map(val => this.filter(val))
    );
    } else {
      this.init = 0;
} 

But that's not working.

Thank you for helping me or at least reading this message.

EDIT: I tried an other method

I have a dictionnarymanagerService:

export class DictionnarymanagerService implements OnInit{

  data: any = ['test2'];
  socket = io.connect('http://localhost:4200');

  constructor() {}

  ngOnInit() {
     this.socket.on('dataSend', function(message) { 
            this.options = message; 
            alert(message); 
        });
  }

And I have in my fileSearchComponent only:

options = []

ngOnInit(){
  this.options = this.dictionnaryManager.data;
  if(this.myControl.value !='') { 
  this.init = 1; 
  this.filteredOptions = this.myControl.valueChanges
  .pipe(
      startWith(''),
      map(val => this.filter(val))
    );
} else {
  this.init = 0;
 } 
}

But because socket.on is asynchrone I don't have the right value (options takes the value 'test2. How can I do to send the value of data after the end of the socket.on()

Adrien Voisin
  • 93
  • 3
  • 11
  • can you try adding a 1 or 2 second timeout around the `socket.emit()` bit of code? i suspect the value is emitted before the page has rendered, meaning the data is send before you can read it – mast3rd3mon Jul 10 '18 at 08:15
  • If it was the case I wouldn't be able to display the data with the alert, isnt it ? – Adrien Voisin Jul 10 '18 at 08:20
  • I misread that part, so you can alert this.options but not message? – mast3rd3mon Jul 10 '18 at 08:21
  • when I'm on the `socket.on()` I can see both the message and this.options but I when I'm not in it I still have `this.options=[]` even when I try to display it with a button. I thought it was a problem with the asynchronous function but it seems to be something else. As if the this.options in the `socket.on()` and the `options` were 2 differents objects. – Adrien Voisin Jul 10 '18 at 08:25
  • do you have a class/component in the filesearch.component.ts file? did you strip out the parts that arent needed? – mast3rd3mon Jul 10 '18 at 08:29
  • A class/component ? Yes I don't write all the content of the filesearch.component.ts file – Adrien Voisin Jul 10 '18 at 08:32
  • Your socket emit only when a client connect ? what is the answer exactly send by the server (typeOf) ? – cagliostro Jul 10 '18 at 15:38

1 Answers1

0

You don't use arrow functions, so this refers to the function you provide in socket.on. Arrow functions don't capture this.

You can checkout this question for more information: Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?

Following code should work because of the arrow function not capturing this, therefore this still refers to the instance of your component class:

ngOnInit() {
    this.socket.on('dataSend', message => this.options = message);
SirDieter
  • 309
  • 2
  • 9