在 Promise 之外获取变量值
Get variable value outside of Promise
我在 AngularJs 中有一项服务,它将 return 来自数据库的值。
userData.getUserData(function(response) {
$scope.uid = response
});
当我在控制器中注入此服务时,它将 return 一个 Promise,
但是我在我的功能之外需要这个 Promise 值,我该怎么做?
您所讨论的问题与以下事实有关:您在承诺 return 之前尝试使用 $scope.uid
。
你可以通过几个步骤来解决这样的问题,主要是你可以在使用之前初始化作用域变量。例如,如果 response
是一个对象,你可以这样做:
$scope.uid = {};
userData.getUserData(function(response) {
$scope.uid = response;
});
那么你的 var 就不会是未定义的。但是你也应该考虑你何时以及如何使用这个变量,无论你是否想要这样初始化都会影响。
如果你这样登录,它会起作用
userData.getUserData(function(response) {
$scope.uid = response;
console.log($scope.uid);
});
如果你这样记录,它将不会工作,因为这个日志不会等待你承诺return,然后再记录;
userData.getUserData(function(response) {
$scope.uid = response;
});
console.log($scope.uid);
您需要提供更多信息以确定如何最好地处理使用此 returned 信息和局部变量。但是这个问题的总体思路是您试图在承诺返回之前记录变量。
TL:DR 你可以在函数外访问$scope.uid,你需要等待响应给它数据在它进入内部之前,如果您不希望它开始时可以初始化它 undefined
UPDATE:您需要使用回调来触发第二个调用在您收到第一个回调之后
userData.getUserData(function(response) {
$scope.postRequest(response);
});
$scope.postRequest = function(val) {
$firebaseArray($firebaseRef.requests.child($scope.uid)).$add(val);
console.log(val) console.log($scope.request);
}
您的问题已修复:https://plnkr.co/edit/KbVoni3jfnHm54M80kYl?p=preview
您必须等到从 userData.getUserData 获取响应的过程完成。
据我所知有3种方法可以解决这个问题:
使用回调
function getUserData(callback){
userData.getUserData(function(response) {
callback(response);
});
}
然后你调用那个函数
getUserData(function(response){
$scope.uid = response;
// then you can proceed and use the $scope.uid here
});
将其包装在函数中
getUserData(function(response){
callAnotherFunction(response);
});
function callAnotherFunction(response){
console.log(response);
// You can use the value inside this function
}
或使用超时
可以使用$timeout给请求时间,分配给$scope.uid
从你的 plunker 代码中你有一个看起来像这样的服务:
angular.module('plunker');
.service('myService', function($firebaseRef, $firebaseObject){
this.getUserData = function(el) {
$firebaseObject($firebaseRef.users.child(this.localStorage().uid)).$loaded(function(data) {
el(data);
})
}
});
和这样的控制器:
app.controller('MainCtrl', function($scope, myService) {
myService.getUserData(function(response) {
$scope.uid = response;
})
console.log($scope.uid);
$scope.postRequest = function(val) {
$firebaseArray($firebaseRef.requests.child($scope.uid)).$add(val);
console.log(val)
console.log($scope.request);
}
});
问题是第 console.log($scope.uid);
行打印 undefined
.
您正在考虑标准阻塞编程,但在这种情况下,对 getUserData
的调用是非阻塞的,这意味着您不等待 response
,而是您只需将请求发送到服务器 (Firebase) 并继续执行下一条语句 console.log
.
回调function(response) { $scope.uid = response; }
将在客户端读取服务器返回的成功响应(HTTP 2xx)时被调用。这至少需要请求传输到服务器和响应返回的时间 + 服务器实际获取数据所需的时间。例如 150ms.
所以,基本上在执行 console.log
语句时,response
回调仍然没有被调用,即。 $scope.uid
未设置,这意味着 console.log
将打印 undefined
.
要解决此问题,您需要在回调本身中执行您的代码,这取决于服务器的响应。例如这样的事情:
app.controller('MainCtrl', function($scope, myService) {
myService.getUserData(function(response) {
$scope.uid = response;
console.log($scope.uid);
// and any other code which depends on the $scope.uid
});
// ...
});
最酷的因素是通过 $q
服务使用 AngularJS promises。例如,您可以像这样重新定义您的服务:
angular.module('plunker');
.service('myService', function($q, $firebaseRef, $firebaseObject){
var deferred = $q.defer();
this.getUserData = function(el) {
$firebaseObject($firebaseRef.users.child(this.localStorage().uid)).$loaded(function(data) {
deferred.resolve(data);
});
};
return deferred.promise;
});
然后在您的控制器中,您可以像这样使用您的服务方法:
app.controller('MainCtrl', function($scope, myService) {
myService.getUserData()
.then(function(data) {
$scope.uid = data;
console.log($scope.uid);
// and any other code
// you can also return promises here and then chain
// them, read about AngularJS promises
});
// ...
});
这与前面的示例基本相同,但增加了可读性更好的好处,这是通过避免回调地狱来实现的。
我注意到您有使用 $scope.uid
的 postRequest
函数。我猜如果你没有 $scope.uid
,你不想执行这个函数。我还猜测这个函数是由某些事件调用的,比如点击一个按钮。我的建议是在加载 $scope.uid
之前禁用按钮或任何其他调用此功能的东西。
例如像这样:
<button type="button" ng-click="postRequest(something)" ng-disabled="uid === undefined">Post</button>
希望对您有所帮助。
我在 AngularJs 中有一项服务,它将 return 来自数据库的值。
userData.getUserData(function(response) {
$scope.uid = response
});
当我在控制器中注入此服务时,它将 return 一个 Promise, 但是我在我的功能之外需要这个 Promise 值,我该怎么做?
您所讨论的问题与以下事实有关:您在承诺 return 之前尝试使用 $scope.uid
。
你可以通过几个步骤来解决这样的问题,主要是你可以在使用之前初始化作用域变量。例如,如果 response
是一个对象,你可以这样做:
$scope.uid = {};
userData.getUserData(function(response) {
$scope.uid = response;
});
那么你的 var 就不会是未定义的。但是你也应该考虑你何时以及如何使用这个变量,无论你是否想要这样初始化都会影响。
如果你这样登录,它会起作用
userData.getUserData(function(response) {
$scope.uid = response;
console.log($scope.uid);
});
如果你这样记录,它将不会工作,因为这个日志不会等待你承诺return,然后再记录;
userData.getUserData(function(response) {
$scope.uid = response;
});
console.log($scope.uid);
您需要提供更多信息以确定如何最好地处理使用此 returned 信息和局部变量。但是这个问题的总体思路是您试图在承诺返回之前记录变量。
TL:DR 你可以在函数外访问$scope.uid,你需要等待响应给它数据在它进入内部之前,如果您不希望它开始时可以初始化它 undefined
UPDATE:您需要使用回调来触发第二个调用在您收到第一个回调之后
userData.getUserData(function(response) {
$scope.postRequest(response);
});
$scope.postRequest = function(val) {
$firebaseArray($firebaseRef.requests.child($scope.uid)).$add(val);
console.log(val) console.log($scope.request);
}
您的问题已修复:https://plnkr.co/edit/KbVoni3jfnHm54M80kYl?p=preview
您必须等到从 userData.getUserData 获取响应的过程完成。
据我所知有3种方法可以解决这个问题:
使用回调
function getUserData(callback){
userData.getUserData(function(response) {
callback(response);
});
}
然后你调用那个函数
getUserData(function(response){
$scope.uid = response;
// then you can proceed and use the $scope.uid here
});
将其包装在函数中
getUserData(function(response){
callAnotherFunction(response);
});
function callAnotherFunction(response){
console.log(response);
// You can use the value inside this function
}
或使用超时
可以使用$timeout给请求时间,分配给$scope.uid
从你的 plunker 代码中你有一个看起来像这样的服务:
angular.module('plunker');
.service('myService', function($firebaseRef, $firebaseObject){
this.getUserData = function(el) {
$firebaseObject($firebaseRef.users.child(this.localStorage().uid)).$loaded(function(data) {
el(data);
})
}
});
和这样的控制器:
app.controller('MainCtrl', function($scope, myService) {
myService.getUserData(function(response) {
$scope.uid = response;
})
console.log($scope.uid);
$scope.postRequest = function(val) {
$firebaseArray($firebaseRef.requests.child($scope.uid)).$add(val);
console.log(val)
console.log($scope.request);
}
});
问题是第 console.log($scope.uid);
行打印 undefined
.
您正在考虑标准阻塞编程,但在这种情况下,对 getUserData
的调用是非阻塞的,这意味着您不等待 response
,而是您只需将请求发送到服务器 (Firebase) 并继续执行下一条语句 console.log
.
回调function(response) { $scope.uid = response; }
将在客户端读取服务器返回的成功响应(HTTP 2xx)时被调用。这至少需要请求传输到服务器和响应返回的时间 + 服务器实际获取数据所需的时间。例如 150ms.
所以,基本上在执行 console.log
语句时,response
回调仍然没有被调用,即。 $scope.uid
未设置,这意味着 console.log
将打印 undefined
.
要解决此问题,您需要在回调本身中执行您的代码,这取决于服务器的响应。例如这样的事情:
app.controller('MainCtrl', function($scope, myService) {
myService.getUserData(function(response) {
$scope.uid = response;
console.log($scope.uid);
// and any other code which depends on the $scope.uid
});
// ...
});
最酷的因素是通过 $q
服务使用 AngularJS promises。例如,您可以像这样重新定义您的服务:
angular.module('plunker');
.service('myService', function($q, $firebaseRef, $firebaseObject){
var deferred = $q.defer();
this.getUserData = function(el) {
$firebaseObject($firebaseRef.users.child(this.localStorage().uid)).$loaded(function(data) {
deferred.resolve(data);
});
};
return deferred.promise;
});
然后在您的控制器中,您可以像这样使用您的服务方法:
app.controller('MainCtrl', function($scope, myService) {
myService.getUserData()
.then(function(data) {
$scope.uid = data;
console.log($scope.uid);
// and any other code
// you can also return promises here and then chain
// them, read about AngularJS promises
});
// ...
});
这与前面的示例基本相同,但增加了可读性更好的好处,这是通过避免回调地狱来实现的。
我注意到您有使用 $scope.uid
的 postRequest
函数。我猜如果你没有 $scope.uid
,你不想执行这个函数。我还猜测这个函数是由某些事件调用的,比如点击一个按钮。我的建议是在加载 $scope.uid
之前禁用按钮或任何其他调用此功能的东西。
例如像这样:
<button type="button" ng-click="postRequest(something)" ng-disabled="uid === undefined">Post</button>
希望对您有所帮助。