AngularJS 控制器中回调函数的范围问题
Scoping issue in callback function in AngularJS controller
我有以下 angular 应用程序 (JSFiddle):
HTML
<form data-ng-app="jsApDemo" data-ng-controller="loginCtrl">
<label for="username">Username:</label>
<input type="text" id="username" data-ng-model="username" />
<br />
<label for="password">Password:</label>
<input type="password" id="password" data-ng-model="password" />
<br />
<button type="submit" data-ng-click="executeLogIn()">Log in</button>
<br />
<label for="authstatus">Authentication status:</label>
<input type="text" id="authstatus" readonly value="{{ authStatus }}" />
</form>
这是一个简单的登录表单,当用户点击提交时,我想在控制器中执行一个功能loginCtrl
。 loginCtrl
调用进行实际身份验证过程的服务。
JavaScript
// the controller and its module
angular.module('jsApDemo', ['Core'])
.controller('loginCtrl', ['$scope', 'Connection', function ($scope, Connection) {
$scope.authStatus = 'unauthenticated';
$scope.executeLogIn = function () {
$scope.authStatus = 'authenticating';
Connection.sessionInitialize({
username: $scope.username,
password: $scope.password
}, function (error, status) {
if (!error) {
/***************************
* THIS LINE IS THE CULPRIT
***************************/
$scope.authStatus = status;
}
});
};
}]);
// the service and its module
angular.module('Core', []).service('Connection', function () {
this.sessionInitialize = function (options, callback) {
if (!options || !options.username || !options.password) {
callback('Username, and password are mandatory', null);
return;
}
setTimeout(function () {
callback(null, 'authenticated');
}, 1000);
};
});
在服务Connection
中,我使用了一个setTimeout
(注意:setTimeout
被用作异步调用的占位符。我的原始代码没有setTimeout
。它调用了第三方库中的异步函数。我无法使用代码中包含的调用来创建 JSFiddle。所以我用 setTimeout
替换了对该库的调用以演示异步代码的性质)。
当我尝试从 Connection.sessionInitialize
的回调函数中访问 $scope
时出现问题。调试后我发现以下行不起作用:
/***************************
* THIS LINE IS THE CULPRIT
***************************/
$scope.authStatus = status;
这似乎是一个范围问题,但是在该行之前的一个简单的 console.log($scope)
语句表明 $scope
具有正确的值。然而,文本框 #authstatus
的 value
属性绑定到 $scope.authStatus
并没有改变。
我做错了什么?
感谢@RahilWazir,我想出了一个解决方案:
/***************************
* THIS LINE IS THE CULPRIT
***************************/
$scope.$apply(function () {
$scope.authStatus = status;
});
setTimeout
是罪魁祸首,因为它 运行 是回调,更新范围,但 运行 摘要循环没有,这使得双向数据绑定上班。请改用 $timeout
服务:
$timeout(function () {
callback(null, 'authenticated');
}, 1000);
我有以下 angular 应用程序 (JSFiddle):
HTML
<form data-ng-app="jsApDemo" data-ng-controller="loginCtrl">
<label for="username">Username:</label>
<input type="text" id="username" data-ng-model="username" />
<br />
<label for="password">Password:</label>
<input type="password" id="password" data-ng-model="password" />
<br />
<button type="submit" data-ng-click="executeLogIn()">Log in</button>
<br />
<label for="authstatus">Authentication status:</label>
<input type="text" id="authstatus" readonly value="{{ authStatus }}" />
</form>
这是一个简单的登录表单,当用户点击提交时,我想在控制器中执行一个功能loginCtrl
。 loginCtrl
调用进行实际身份验证过程的服务。
JavaScript
// the controller and its module
angular.module('jsApDemo', ['Core'])
.controller('loginCtrl', ['$scope', 'Connection', function ($scope, Connection) {
$scope.authStatus = 'unauthenticated';
$scope.executeLogIn = function () {
$scope.authStatus = 'authenticating';
Connection.sessionInitialize({
username: $scope.username,
password: $scope.password
}, function (error, status) {
if (!error) {
/***************************
* THIS LINE IS THE CULPRIT
***************************/
$scope.authStatus = status;
}
});
};
}]);
// the service and its module
angular.module('Core', []).service('Connection', function () {
this.sessionInitialize = function (options, callback) {
if (!options || !options.username || !options.password) {
callback('Username, and password are mandatory', null);
return;
}
setTimeout(function () {
callback(null, 'authenticated');
}, 1000);
};
});
在服务Connection
中,我使用了一个setTimeout
(注意:setTimeout
被用作异步调用的占位符。我的原始代码没有setTimeout
。它调用了第三方库中的异步函数。我无法使用代码中包含的调用来创建 JSFiddle。所以我用 setTimeout
替换了对该库的调用以演示异步代码的性质)。
当我尝试从 Connection.sessionInitialize
的回调函数中访问 $scope
时出现问题。调试后我发现以下行不起作用:
/***************************
* THIS LINE IS THE CULPRIT
***************************/
$scope.authStatus = status;
这似乎是一个范围问题,但是在该行之前的一个简单的 console.log($scope)
语句表明 $scope
具有正确的值。然而,文本框 #authstatus
的 value
属性绑定到 $scope.authStatus
并没有改变。
我做错了什么?
感谢@RahilWazir,我想出了一个解决方案:
/***************************
* THIS LINE IS THE CULPRIT
***************************/
$scope.$apply(function () {
$scope.authStatus = status;
});
setTimeout
是罪魁祸首,因为它 运行 是回调,更新范围,但 运行 摘要循环没有,这使得双向数据绑定上班。请改用 $timeout
服务:
$timeout(function () {
callback(null, 'authenticated');
}, 1000);