5

我真的很喜欢自动解包承诺的干净(而且我认为很容易遵循)方式:

$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 要求。有没有其他人解决过这个问题,或者找到了一种更干净的方法?

4

2 回答 2

10

首先你不需要使用

DataService.query({something:"etc"}).$promise.then(function(data){
    $scope.myData = data;
});

这显然是指 a $resource,因为$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({...});

如果您必须使用返回承诺的第三方服务,您可以实现您的通用函数以提供类似的功能:

.run(function ($rootScope) {
    $rootScope.promiseToArray = function (promise) {
        var arr = [];
        promise.then(function (data) {
            data.forEach(function (item) {
                arr.push(item);
            });
        });
        return arr;
    };
});

.controller('someCtrl', function ($scope, ThirdPartyService) {
    $scope.data = $scope.promiseToArray(ThirdPartyService.fetchData());
});

另请参阅这个简短的演示


上述示例仅用于说明目的,并非生产就绪代码。
我是一个真实世界的应用程序,你需要优雅地处理异常、拒绝等。

于 2014-07-01T20:31:36.210 回答
0

如果我们真的想通过在 .config() 函数中将选项设置为 true ,我们可以重新启用展开:

.config(function($parseProvider) {
   $parseProvider.unwrapPromises(true) ;
});
于 2016-10-05T05:42:04.147 回答