2014-07-01 19 views
5

Tôi thực sự thích sạch (và tôi nghĩ rằng dễ dàng để làm theo) cách mà những lời hứa được autounwrapped:Angularjs - cách sạch nhất để thêm lời hứa để phạm vi, bây giờ mà kiễu góc phản đối auto unwrapping những lời hứa

$scope.myData = DataService.query({something:"etc"}); // done; 

Và tôi thực sự không quan tâm cho những gì có vẻ là cách tiêu chuẩn để làm việc đó bây giờ, nếu không có sự unwrapping tự động:

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

những gì tôi muốn thấy là một cái gì đó như thế này:

$scope.pulseData = $scope.setPromise(CitsciAnalytics.pulse({ 
    projId:"yardmap" 
})); 

Nhưng tôi không thể thấy làm thế nào để điều đó xảy ra. Gần nhất tôi nhận được là:

$scope.pulseData = $scope.setPromise("pulseData", CitsciAnalytics.pulse({ 
    projId:"yardmap" 
})); 

Sử dụng chức năng thêm vào phạm vi root:

.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"); 
     } 
    }; 
}]); 

nhưng tôi không thích những yêu cầu unDRY vì phải vượt qua phạm vi tên biến như một chuỗi thêm . Có ai khác đã giải quyết vấn đề này hay không, hoặc xem cách làm điều này một cách rõ ràng hơn?

Trả lời

10

Trước hết bạn không cần phải sử dụng

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

trong đó đề cập rõ ràng đến một $resource, vì $resource sẽ trả về một mảng rỗng hoặc đối tượng và điền nó với dữ liệu khi nhận được.

Như vậy, với một lớp $resource, bạn vẫn có thể sử dụng

$scope.myData = DetaService.query(...); 

$resource 's mô hình cũng là một cách tiếp cận tốt để làm theo dịch vụ 'data-quyến rũ' của riêng bạn: Return và mảng trống và điền dữ liệu khi họ đến.

Ví dụ:

.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({...}); 

Nếu bạn phải sử dụng dịch vụ thrid bên đó trả về một lời hứa, bạn có thể thực hiện chức năng chung của bạn để cung cấp chức năng tương tự:

.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()); 
}); 

Xem thêm, đây, short demo.


Các mẫu trên đây chỉ nhằm mục đích minh họa và không mã sản xuất-ready.
tôi một ứng dụng thực tế, bạn sẽ cần phải xử lý một cách duyên dáng ngoại lệ, từ chối, vv

+0

ah, nhờ làm rõ, còn những gì pixelbits đề nghị, tốt đẹp để có cách chính thức để đi về phía trước với this- – chrismarx

+0

như vậy, đối với người sử dụng $ tài nguyên, điều này không thực sự ảnh hưởng đến bất cứ điều gì ? https://github.com/angular/angular.js/commit/5dc35b527b3c99f6544b8cb52e93c6510d3ac577 – chrismarx

+0

Chính xác! Theo ** [tài liệu] (https://docs.angularjs.org/api/ngResource/service/$resource) **: _ "Điều quan trọng là nhận ra rằng việc gọi phương thức đối tượng' $ resource' ngay lập tức trả về một tham chiếu rỗng (đối tượng hoặc mảng tùy thuộc vào 'isArray') Một khi dữ liệu được trả về từ máy chủ, tham chiếu hiện có được điền bằng dữ liệu thực tế. Đây là một mẹo hữu ích vì thường tài nguyên được gán cho một mô hình mà [...] Điều này có nghĩa là trong hầu hết các trường hợp, người ta không bao giờ phải viết một hàm gọi lại cho các phương thức hành động. "_ – gkalpak

0

Chúng ta có thể kích hoạt lại unwrapping nếu chúng ta thực sự muốn bằng cách thiết lập các tùy chọn để đúng trong một.config() chức năng:

.config(function($parseProvider) { 
    $parseProvider.unwrapPromises(true) ; 
}); 
Các vấn đề liên quan