我非常喜欢承诺被自动包装的干净(并且我认为易于遵循)方式:
$scope.myData = DataService.query({something:"etc"}); // done;
DataService.query({something:"etc"}).$promise.then(function (data){ $scope.myData = data; });
我想看到的是这样的:
$scope.pulseData = $scope.setPromise(CitsciAnalytics.pulse({ projId:"yardmap" }));
但我看不出如何实现这一目标.我得到的最接近的是:
$scope.pulseData = $scope.setPromise("pulseData",CitsciAnalytics.pulse({ projId:"yardmap" }));
.run(["$rootScope","$log",function ($rootScope,$log) { //parent method to avoid promise unwrapping boilerplate $rootScope.setPromise = function (scopeVar,promise) { if (arguments.length === 2 && promise && promise.$promise) { var scope = this; promise.$promise.then(function (data){ scope[scopeVar] = data; }); } else { $log.error("$rootScope.setPromise has invalid arguments"); } }; }]);
但我不喜欢unDRY要求必须将范围变量名称作为附加字符串传递.有没有其他人解决这个问题,或者看到一种方法更干净地做到这一点?
解决方法
首先,您不需要使用
DataService.query({something:"etc"}).$promise.then(function(data){ $scope.myData = data; });
这显然是指$资源,因为$resource将返回一个空数组或对象,并在数据到达时填充它.
因此,使用$resource类,您仍然可以使用
$scope.myData = DetaService.query(...);
$resource的范例也是在你自己的“数据获取”服务中遵循的一种好方法:返回并清空数组,并在数据到达时填充数据.
例如.:
.factory('DataService',function ($http) { function query(params) { var data = []; $http.get('/some/url/with/params').then(function (response) { response.data.forEach(function (item) { data.push(item); }); }); return data; } return { query: query }; }); .controller('someCtrl',function ($scope,DataService) { $scope.data = DataService.query({...});
如果必须使用返回promise的thrid-party服务,则可以实现通用函数以提供类似的功能:
.run(function ($rootScope) { $rootScope.promiseToArray = function (promise) { var arr = []; promise.then(function (data) { data.forEach(function (item) { arr.push(item); }); }); return arr; }; }); .controller('someCtrl',ThirdPartyService) { $scope.data = $scope.promiseToArray(ThirdPartyService.fetchData()); });
另见这short demo.
以上示例仅用于说明目的,而非生产就绪代码.我是一个真实的应用程序,你需要优雅地处理异常,拒绝等.