app.controller('ctrl', function($scope){
var socket = io.connect();
this.messages = [];
this.sendMessage = function(){
socket.emit('new message', this.input_message);
this.input_message = '';
}
socket.on('new message', function(data){
this.messages.push(data);
});
});
我正在获取套接字发出的数据,但是当我尝试将该数据推送到messages
数组时,它会显示错误cannot read the property push of undefined
。我做错了什么?
答案 0 :(得分:2)
这不起作用,因为您在套接字范围(this
)中调用this.messages.push(data)
,这与控制器范围不同。这就是this.messages
为undefined
的原因,因为它是在控制器函数范围内声明的,而不是在套接字回调函数范围中声明的。在javascript中,每个函数都有自己的作用域(箭头函数除外)。
app.controller('ctrl', function($scope){
var ctrlContext = this;
var socket = io.connect();
//using the this keyword here means that
//it's in the controller function scope.
this.messages = [];
this.sendMessage = function(){
socket.emit('new message', this.input_message);
this.input_message = '';
}
socket.on('new message', function(data){
//inside the callback function we have a different
//scope, which means that this.messages will be undefined.
//but by referencing the controller function scope, you
//are now able to use the messages property set the
//outer (controller function) scope.
ctrlContext.messages.push(data);
//as you stated, you will also have to call $scope.$apply
//or else the digest cycle will not be triggered.
});
});
但是,如果您想在套接字回调函数中使用this
关键字,则可以使用function.prototype.bind方法执行此操作,该方法允许您设置执行函数的上下文。
var person = {
name: 'John Doe';
}
//Create function and bind to context person
var changeName = function() {
this.name = 'Peter Smith';
}.bind(person);
console.log(person); // {name: 'John Doe'}
changeName(person);
console.log(person); // {name: 'Peter Smith'}
对于你的解决方案,它将类似于:
app.controller('ctrl', function($scope){
var socket = io.connect();
this.messages = [];
var callback = function(data){
this.messages.push(data);
}.bind(this);
socket.on('new message', callback);
});