2016-05-07 2 views
4

Я пытаюсь создать службу WebSocket в угловом 2. Здесь то, что я до сих пор:WebSocket обратного вызова в функции стрелки не устанавливая «это» лексический

import {Injectable} from "angular2/core" 
@Injectable() 
export class ServerService { 

    public ws:WebSocket; 

    public myData = {}; 

    constructor() { 
     let ws = new WebSocket('ws://localhost:8080/'); 

     ws.onopen = (event:Event) => { 
      console.log("Socket has been opened!"); 
     }; 

     ws.onmessage = (event:Event) => { 
      this.myData = JSON.parse(event.data); 
     }; 
    }; 
} 

Проблема заключается в том, когда onmessage прогонов this ключевое слово становится объектом WebSocket, а не моим объектом ServerService.

Кажется, что функция стрелки действует как стандартная функция. Что может быть причиной этого? Есть ли другой способ вернуться к объекту ServerService?

+1

Ваш код хорошо, 'this' будет указывать на ServerService. [проверить консоль на этом plunk] (http://plnkr.co/edit/xdnX78BbQvHItVQJpUYL?p=preview) – Abdulrahman

+0

Я думаю, что вы назначаете «event.data», который имеет тип «объект WebSocket», возможно, это причина, попробуйте использовать консоль перед назначением значения в методе 'onmessage' –

+0

, как вы скажете, что это ключевое слово this является объектом веб-сокета? –

ответ

2

ОК, поэтому, увидев пример Abdulrahmans, работающего в плунге, я подумал, что, возможно, что-то не так с моей окружающей средой. Оказывается, моя машинопись была компиляция в ES5, и вывод:

function ServerService() { 
       var _this = this; 
       this.myData = {}; 
       var ws = new WebSocket('ws://localhost:8080'); 
       ws.onopen = function (event) { 
        console.log("Socket has been opened!"); 
       }; 
       ws.onmessage = function (event) { 
        _this.myData = JSON.parse(event.data); 
       }; 
      } 

Мои стрелки функция были действительно удаляется, а заменяется чем-то, что должно быть функционально эквивалентны (?). Он работает так, как ожидалось, в Firefox, но не в Chrome (где я отлаживался).

Я переключил свой компилятор TypeScript на вывод ES6, и теперь у меня есть функции стрелок в моем JavaScript, и мой код работает как ожидалось в обоих браузерах.

0

Я думаю, что websocket выполнил обратный вызов в контексте соответствующего экземпляра (с помощью метода call или apply).

Обходной состоит из оберточной обработчика событий WebSocket в наблюдаемый:

initializeWebSocket(url) { 
    this.wsObservable = Observable.create((observer) => { 
    this.ws = new WebSocket(url); 

    this.ws.onopen = (e) => { 
     (...) 
    }; 

    this.ws.onclose = (e) => { 
     if (e.wasClean) { 
     observer.complete(); 
     } else { 
     observer.error(e); 
     } 
    }; 

    this.ws.onerror = (e) => { 
     observer.error(e); 
    } 

    this.ws.onmessage = (e) => { 
     observer.next(JSON.parse(e.data)); 
    } 

    return() => { 
     this.ws.close(); 
    }; 
    }).share(); 
} 

Таким образом, вы сможете использовать функции стрелок и контекстуальное это:

this.wsObservable.subscribe(data => { 
    this.myData = data; 
}); 

эту статью для более подробной информации (раздел «Вспомогательная поддержка»):

1

Я исправил его с помощью Function.prototype.bind(), который доступен только для анонимных функций oldschool, а не для функций со стрелками.

Таким образом, вместо:

ws.onmessage = (event:Event) => { 
    this.myData = JSON.parse(event.data); 
}; 

я сделал:

ws.onmessage = function(event:Event) { 
    this.myData = JSON.parse(event.data); 
}.bind(this);