Angularjs:我如何制作服务代码;看起来是同步的;?
如何使角度服务代码“看起来是同步的” 当我清理控制器并将业务逻辑代码放入服务中时,我的问题出现了。到现在为止,一直都还不错。现在我想在服务函数中“等待”,直到所有异步调用都返回,然后返回。我该怎么做 为了说明我的问题,假设您有一个控制器代码,它只是:Angularjs:我如何制作服务代码;看起来是同步的;?,angularjs,asynchronous,promise,angular-promise,Angularjs,Asynchronous,Promise,Angular Promise,如何使角度服务代码“看起来是同步的” 当我清理控制器并将业务逻辑代码放入服务中时,我的问题出现了。到现在为止,一直都还不错。现在我想在服务函数中“等待”,直到所有异步调用都返回,然后返回。我该怎么做 为了说明我的问题,假设您有一个控制器代码,它只是: 从后端请求一些数据 对数据和数据进行一些处理 将数据交给范围 就像这样: 重构前的DataController: $scope.submitForm = function() { RestBackend.query('something'
$scope.submitForm = function() {
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
$scope.data = data;
});
};
$scope.submitForm = function() {
DataService.getData().then(function(data) {
$scope.data = data;
});
};
this.query = function() {
var dataDefer = $q.defer();
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
dataDefer.resolve(data);
});
return dataDefer.promise;
};
$scope.submitForm = function() {
$scope.data = DataService.getData();
};
很简单。获取数据并填充范围
在重构到controller+服务之后,我最终得到了:
数据控制器重构:
$scope.submitForm = function() {
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
$scope.data = data;
});
};
$scope.submitForm = function() {
DataService.getData().then(function(data) {
$scope.data = data;
});
};
this.query = function() {
var dataDefer = $q.defer();
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
dataDefer.resolve(data);
});
return dataDefer.promise;
};
$scope.submitForm = function() {
$scope.data = DataService.getData();
};
数据服务重构:
$scope.submitForm = function() {
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
$scope.data = data;
});
};
$scope.submitForm = function() {
DataService.getData().then(function(data) {
$scope.data = data;
});
};
this.query = function() {
var dataDefer = $q.defer();
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
dataDefer.resolve(data);
});
return dataDefer.promise;
};
$scope.submitForm = function() {
$scope.data = DataService.getData();
};
我不喜欢这样一个事实,即我必须在控制器中也有承诺。我喜欢承诺,但我想让控制器不知道服务的“实现细节”。这就是我希望控制器代码的样子:
DataController(应该是):
$scope.submitForm = function() {
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
$scope.data = data;
});
};
$scope.submitForm = function() {
DataService.getData().then(function(data) {
$scope.data = data;
});
};
this.query = function() {
var dataDefer = $q.defer();
RestBackend.query('something').then(function(data) {
// do some additional things ...
...
dataDefer.resolve(data);
});
return dataDefer.promise;
};
$scope.submitForm = function() {
$scope.data = DataService.getData();
};
你明白了吗?在控制器中,我不想关心承诺与否。只需等待获取数据,然后使用它。因此,我正在寻找实现以下服务的可能性:
现在是项目2。我不清楚:我怎么能“等到数据被提取”然后才继续?我们的目标是使服务功能看起来是同步的。我认为您拥有的是一个非常好的解决方案。您不必等待承诺得到解决,它违背了异步javascript的目的。问问自己,为什么需要让它同步运行 如果您在html中依赖于promise to be resolve,那么您可以这样做
<div class="alert alert-warning text-center" data-ng-hide="!data.$resolved">
Got data from service.
</div>
从服务中获取数据。
我也认为您的解决方案很好。返回承诺不是服务的实现细节。它是服务API的一部分(服务和服务使用者之间的“合同”) 控制器需要一个承诺来解决数据问题,并根据自己的意愿进行处理。
承诺是如何构建的,数据是如何获取的,等等,这些都是实现细节。
您可以随时将该服务与执行完全不同的操作的服务交换,只要它履行了合同(即返回一个承诺,该承诺与准备好的数据一致)
也就是说,如果您仅在视图中使用数据(即,在获取数据后不直接在控制器中对其进行操作),情况似乎是这样的,那么您可以使用
ngResources
方法:
获取后,返回空数组并用数据填充它:
$scope.data = DataService.getData();
// DataService refactored:
this.getData = function () {
var data = [];
RestBackend.query('something').then(function(responseData) {
// do some additional things ...
...
angular.forEach(responseData, function (item) {
data.push(item);
});
});
return data;
};
顺便说一句,在当前(精细)设置中,您需要
$q.defer()
。您可以使用承诺链接:
this.query = function() {
return RestBackend.query('something').then(function(data) {
// do some additional things ...
...
return data;
});
};
当您使用
ngRoute
时,我建议您在路由配置中解析数据,并在解析完所有数据后加载视图
$routeProvider
.when('/your-url', {
templateUrl: 'path/to/your/template.html',
controller: 'YourCtrl',
// that's the point !
resolve: {
superAwesomeData: function (DataService) {
return DataService.getData();
}
}
});
angular.module('youModule')
.controller('YourCtrl', function (superAwesomeData) {
// superAwesomeData === [...];
});
现在,可以将superwesomedata
注入控制器,它将包含已解析的数据
$routeProvider
.when('/your-url', {
templateUrl: 'path/to/your/template.html',
controller: 'YourCtrl',
// that's the point !
resolve: {
superAwesomeData: function (DataService) {
return DataService.getData();
}
}
});
angular.module('youModule')
.controller('YourCtrl', function (superAwesomeData) {
// superAwesomeData === [...];
});
您是否在项目中使用了
ngRoute
?我认为您拥有的是一个非常好的解决方案。您不必等待承诺得到解决,它违背了异步javascript的目的。问问自己,为什么要让它同步运行?将我的评论移至answer@meriadec:是的,我正在使用ngRoute。。。但你为什么要问?事实上,我想在控制器代码中等待数据,而不是在HTML模板中。无论如何,谢谢你的提示。另外,在控制器中,我当然希望避免阻塞和等待,我想知道是否会有一种模式以某种方式进行非阻塞等待…@andimeter:LOL.non-blocking wait(也称为promise:P)@andimeter是的,不幸的是没有等待只是承诺或回调方法。有趣。当我了解ngRoute时,我有点忽略了属性“resolve”。所以,我现在又学到了一些东西;)无论如何,AFAIU,您的建议会阻止控制器的实例化,直到所有问题都得到解决。相反,在我的例子中,我有一个实例化的控制器,并且希望在一个处理程序方法中暂停语句流,而不是延迟控制器实例化。如果我可以接受2个答案,我也会接受这个。我将绿色复选标记授予按时间顺序排列的第一个答案。但我不得不说,在专家系统的回答中有一些非常有用的提示。我求助于向上投票。。。