Chuyển phạm vi hiện tại sang Dịch vụ AngularJS


106

Chuyển "hiện tại" $scopesang dịch vụ AngularJS có đúng không?

Tôi đang ở trong tình huống mà tôi có một dịch vụ $ khi biết rằng nó chỉ được sử dụng bởi một bộ điều khiển và tôi muốn tham chiếu đến phạm vi của bộ điều khiển trong chính các phương thức dịch vụ $.

Điều này có đúng về mặt triết học không?

Hay tốt hơn là tôi nên phát các sự kiện tới $ rootScope và sau đó làm cho bộ điều khiển của tôi lắng nghe chúng?


1
Bạn có thể cho chúng tôi biết cụ thể hơn những gì bạn đang cố gắng làm không? Có lẽ việc đẩy phạm vi lên dịch vụ là không cần thiết?
ganaraj

Chà, nó không quá khó. Đơn giản, tôi muốn có thể truy cập các $scopethuộc tính và gọi $scope.$applykhi cần thiết.
SC

Ngoài ra, hãy nói rằng tôi muốn áp dụng các thay đổi đến từ dịch vụ $ vào phạm vi $. Hy vọng nó rõ ràng hơn bây giờ.
SC

8
Tôi khuyên bạn nên đặt các thuộc tính $ scope mà bạn muốn dịch vụ của mình truy cập vào chính dịch vụ đó (thay vì đặt chúng trong bộ điều khiển). Dịch vụ là nơi tốt hơn để lưu trữ mô hình / dữ liệu hơn là bộ điều khiển.
Mark Rajcok

@MarkRajcock Tôi cũng đang cố gắng hiểu vấn đề này. Hiện tại tôi chỉ đang gọi một dịch vụ và đính kèm dữ liệu được cung cấp vào bộ điều khiển $scope... làm thế nào bộ điều khiển sẽ truy cập trực tiếp vào dữ liệu trong dịch vụ và chuyển nó đến chế độ xem mà không làm điều này?
drjimmie1976

Câu trả lời:


67

Để cho bộ điều khiển biết khi có điều gì đó không đồng bộ xảy ra, hãy sử dụng Angular hứa hẹn .

Để kích hoạt $apply, bạn không cần phạm vi, bạn có thể gọi $rootScope.$apply, vì không có sự khác biệt khi gọi nó trong một phạm vi cụ thể hoặc trong thư mục gốc.

Về việc đọc biến, sẽ tốt hơn nếu bạn nhận được các tham số. Nhưng bạn cũng có thể đọc nó từ phạm vi dưới dạng tham số đối tượng, nhưng tôi sẽ sử dụng tham số, điều đó sẽ làm cho giao diện dịch vụ của bạn rõ ràng hơn nhiều.


Tôi nghĩ đây là câu trả lời giải quyết tốt hơn những nghi ngờ dành cho người mới bắt đầu AngularJS của tôi.
SC

@Caio Cunha Bạn có thể mở rộng lý do tại sao vượt qua một phạm vi không phải là một ý kiến ​​hay? Chính xác là tôi đang gặp sự cố này, tôi muốn thêm một số nội dung vào $scopethông qua cuộc gọi tới dịch vụ sử dụng executeSql()chức năng không đồng bộ. Xem xét 3 tùy chọn (1) sử dụng một lệnh gọi lại trên hàm không đồng bộ, sau đó gọi $scope.$apply... điều này hoạt động, nhưng không tốt (2) chuyển $scopeđến hàm không đồng bộ, sau đó gọi theScope.$apply()... điều này cũng hoạt động (3) sử dụng một lời hứa. .. chưa thử cái này. Tại sao một lời hứa là cách tốt nhất? Cảm ơn!
drjimmie1976

15

Tôi sẽ nói nếu chức năng của bạn chỉ dành riêng cho một bộ điều khiển thì bạn không cần dịch vụ.

Nhiệm vụ của bộ điều khiển là thao tác với mô hình cụ thể trong khi một dịch vụ phải xử lý các tác vụ toàn cục. Tôi thà gắn bó với mô hình này thay vì trộn lẫn mọi thứ.

Đây là những gì tài liệu nói

Dịch vụ

Các dịch vụ Angular là các ứng dụng đơn thực hiện các tác vụ cụ thể chung cho các ứng dụng web

Bộ điều khiển

Trong Angular, bộ điều khiển là một hàm JavaScript (kiểu / lớp) được sử dụng để tăng cường các phiên bản của Phạm vi góc, ngoại trừ phạm vi gốc.

Tái bút: Ngoài điều đó ra, nếu bạn cần hiểu rõ, bạn cũng có thể đưa $ rootScope vào trong dịch vụ của mình.


2
Cảm ơn. Trả lời tuyệt vời. Đi sâu vào tình huống của tôi, vấn đề là tôi đang sử dụng Service vì tôi muốn có một singleton. Chỉ có một bộ điều khiển sử dụng dịch vụ, nhưng bộ điều khiển này có thể được khởi tạo nhiều lần trong vòng đời ứng dụng, vì vậy tôi thực sự muốn Dịch vụ luôn ở trạng thái như cũ.
SC

Dù sao thì việc làm rõ về cách gọi $applyhoặc $digesttới $ rootScope hoàn toàn có ý nghĩa đối với tôi.
SC

1
Tôi vẫn sẽ tách nó thành một Dịch vụ để thử nghiệm.
bluehallu

Nếu chức năng dành riêng cho một phiên bản của bộ điều khiển thì bạn có thể bỏ qua việc triển khai một dịch vụ, nhưng nếu không thì không vì bạn hy sinh khả năng chia sẻ trạng thái giữa các phiên bản đó. Hơn nữa, chỉ vì ngày nay có một loại bộ điều khiển duy nhất, điều đó không có nghĩa là ngày mai sẽ không có một bộ điều khiển khác có thể tận dụng chức năng. Ngoài ra, một dịch vụ có thể tránh làm đầy bộ điều khiển. Vì vậy, vấn đề không phải là liệu có một bộ điều khiển duy nhất hay không, mà là chức năng của nó là gì.
Nick

9

Đúng. Bạn có thể chuyển $ scope vào dịch vụ khi khởi tạo nó. Trong phương thức khởi tạo dịch vụ, bạn có thể gán phạm vi cho một cái gì đó như thế này._scope và sau đó tham chiếu phạm vi trong dịch vụ!

angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {

    $scope.someVar = 4;

    $scope.blahService = new blahService($scope);

});

angular.module('blah').factory('blahService', function() {

    //constructor
    function blahService(scope) {
        this._scope = scope;

        this._someFunction()
    }

    //wherever you'd reference the scope
    blahService.prototype._someFunction = function() {

        this._scope['someVar'] = 5;

    }

    return blahService;

});

1
+1, tuy nhiên, tôi muốn xem một cách để tự động biết từng bộ điều khiển $scopebất cứ khi nào bộ điều khiển đó đưa vào dịch vụ - để không phải gọi một phương thức trên dịch vụ và chuyển $scopeđến nó theo cách thủ công .
Cody

2
@Cody Tôi không khuyên bạn điều đó vì nó mâu thuẫn với Dependency Injection
Coldstar

Đồng ý, +1 vì đã bắn hạ tôi! Có thể là những người bán thịt cũng DIP - tôi sẽ nói, có nguy cơ bị thừa.
Cody

Bạn đang trộn dịch vụ với các nhà máy ở đây. Giải pháp này sử dụng một nhà máy, khác với một dịch vụ. Sự khác biệt chính là một dịch vụ trả về một đối tượng (singleton). Trong khi nhà máy trả về một hàm, hàm này có thể được khởi tạo ( new MyFunction()). Câu hỏi liên quan đến một dịch vụ, nơi gọi điện newkhông phải là một tùy chọn.
Karvapallo

@Karvapallo Điểm tốt. Tôi tin rằng các dịch vụ góc cạnh đề cập đến một nhà máy, dịch vụ và nhà cung cấp (ng-wat)?
user12121234

6

Cá nhân tôi tin rằng chuyển $scopetới một dịch vụ là một ý tưởng tồi , vì nó tạo ra một tham chiếu vòng tròn kinda: bộ điều khiển phụ thuộc vào dịch vụ và dịch vụ phụ thuộc vào phạm vi của bộ điều khiển.

Ngoài việc khó hiểu về mặt quan hệ, những thứ như thế này cuối cùng lại cản đường người thu gom rác.

Cách tiếp cận ưa thích của tôi là đặt một đối tượng miền trong phạm vi bộ điều khiển và chuyển nó cho dịch vụ. Cách này dịch vụ hoạt động bất kể nó được sử dụng bên trong bộ điều khiển hay có thể bên trong dịch vụ khác trong tương lai.

Ví dụ: nếu dịch vụ được cho là đẩy và bật các phần tử từ một mảng errors, mã của tôi sẽ là:

var errors = [];
$scope.errors = errors;
$scope.myService = new MyService(errors);

Sau đó, dịch vụ tương tác với bộ điều khiển bằng cách bật errors. Tất nhiên tôi phải thận trọng về việc không bao giờ xóa toàn bộ tham chiếu mảng, nhưng vào cuối ngày, đó là mối quan tâm chung của JS.

Tôi không bao giờ muốn sử dụng phát thanh truyền hình $applyvà / hoặc những thứ tương tự, bởi vì các phương pháp OO tốt sẽ luôn vượt trội bất cứ thứ gì Angular-magics.


1
Có mã này có bất kỳ sự khác biệt với một này ?:$scope.errors = []; $scope.myService = new MyService($scope.errors);
Soldeplata Saketos

@SoldeplataSaketos - Đúng vậy. errorssống độc lập với $scope. Đó là toàn bộ điểm của câu trả lời này. Xin vui lòng kiểm tra liên kết tôi đã cung cấp trong văn bản. Chúc mừng.
Marco Faustinelli

1
Nếu tôi hiểu đúng thì mã của bạn $scope.errorsđang trỏ đến var errors, và lỗi biến có vẻ thừa đối với tôi, vì nó chỉ là một con trỏ khác. Một tình huống tương tự tôi có thể nghĩ đến và rằng nó ngang nhiên thừa là đoạn mã này: const errors = errors2 = errors3 = []; $scope.errors = errors;. Bạn có đồng ý rằng chỉ với đoạn mã bạn cung cấp thì có vẻ var errors = []là thừa không?
Soldeplata Saketos

Không, không phải. Tôi lặp lại chính mình từng từ một: errorssống độc lập với $scope. Bạn cần hiểu đối tượng miền là gì, cũng như varphép gán là gì. Nếu liên kết tôi cung cấp không đủ, có rất nhiều tài liệu khác có sẵn.
Marco Faustinelli

Vâng, điều đó sẽ chỉ phụ thuộc vào việc triển khai chức năng MyService(errors). Theo hiểu biết của tôi, dịch vụ sẽ tạo ra một mảng ghi nhật ký dựa trên tham số (trong trường hợp này là một con trỏ). Đối với tôi, đó là một mô hình xấu, vì các dịch vụ là các đơn vị trong góc cạnh. Nếu việc triển khai dịch vụ được lập trình tốt, nó sẽ tạo ra mảng trong một biến nội bộ (để tiếp tục là một singleton). Do đó, không có ý nghĩa gì khi khởi tạo biến bên ngoài dịch vụ.
Soldeplata Saketos 25/09/17
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.