回调在Angular2 / Firebase

时间:2016-04-23 18:51:52

标签: javascript typescript firebase angular

我正在尝试理解这里的锣是什么以及为什么如果我以某种方式调用函数并且在以不同的方式调用函数时没有收到错误,我会收到错误。以下是首先产生错误的方法:

  

player.service.ts文件

@Injectable我有

private roomsRef: Firebase;

constructor() {
    this.roomsRef   = new Firebase("https://xxx.firebaseio.com/rooms");
}

postGameActions(roomId: string) {
        console.log("post game actions start on " + roomId);

//error on below 'this'        
        this.roomsRef.child(roomId).child("board").once("value", snap => {
           let board = snap.val();
           //do stuff with 'board' object
        });
}
  

room.component.ts文件

activateTimer(roomId: string, roomName: string, callback) {
    var timer = setInterval(redirectTimer, 1000);
    var seconds: number = 5;
    var timerHtml = document.getElementById("divRedirectTimer" + roomName);
    timerHtml.innerHTML = "[" + seconds + "]";

    function redirectTimer() {
        timerHtml.innerHTML = "[" + (seconds--) + "]";
        if(seconds === 0) {
            clearInterval(timer);
            callback(roomId);
        }
    };
}
  

调用像这样的非工作版本

activateTimer(room.id, room.name, _playerService.postGameActions)

错误:

EXCEPTION: TypeError: this is undefined
  

工作版

在这样的情况下工作正常但不使用setInterval(),因为activateTimer只调用服务方法

  

room.component.ts文件

activateTimer(roomId: string, roomName: string) {
    var timer = setInterval(redirectTimer, 1000);
    var seconds: number = 5;
    var timerHtml = document.getElementById("divRedirectTimer" + roomName);
    timerHtml.innerHTML = "[" + seconds + "]";

    function redirectTimer() {
        timerHtml.innerHTML = "[" + (seconds--) + "]";
        if(seconds === 0) {
            clearInterval(timer);
        }
    }

    this._playerService.postGameActions(roomId);
  

调用像这样的工作版

activateTimer(room.id, room.name)

当我将postGameActions称为回调时,为什么'this'未定义?我确定我在这里遗漏了一些简单的东西

1 个答案:

答案 0 :(得分:5)

您需要将调用包装成箭头函数:

activateTimer(room.id, room.name, () => {
  _playerService.postGameActions();
});

你的代码中的问题是你直接引用一个函数,所以你会丢失它将被执行的对象。

另一种方法是使用bind方法:

activateTimer(room.id, room.name, _playerService.postGameActions.bind(_playerService);