Geçerli kapsamı bir AngularJS Hizmetine geçirme


106

"Akımı" $scopebir AngularJS hizmetine geçirmek doğru mu?

Yalnızca bir denetleyici tarafından tüketildiğini bilen bir $ hizmetim olduğu bir durumdayım ve denetleyicinin kapsamına $ hizmet yöntemlerinin kendisinde bir referans vermek istiyorum.

Bu felsefi olarak doğru mu?

Ya da olayları $ rootScope'a yayınlayıp ardından denetleyicimin onları dinlemesini sağlasam daha iyi olur?


1
Ne yapmaya çalıştığınızı bize daha ayrıntılı olarak bildirebilir misiniz? Belki de kapsamı hizmete itmek hiç gerekli değildir?
ganaraj

O kadar da zor değil. Basitçe, $scopemülklere erişebilmek ve $scope.$applygerektiğinde arayabilmek istiyorum .
SC

Artı, $ hizmetinden gelen değişiklikleri $ kapsamına uygulamak istediğimi söyleyin. Umarım şimdi daha nettir.
SC

8
Hizmetinizin erişmesini istediğiniz $ kapsam özelliklerini hizmetin kendisine koymanızı öneririm (denetleyicide bulundurmak yerine). Hizmetler, modelleri / verileri depolamak için denetleyicilerden daha iyi yerlerdir.
Mark Rajcok

@MarkRajcock Bu konuyu da anlamaya çalışıyorum. Şu anda sadece bir hizmeti arıyorum ve sunulan verileri denetleyiciye ekliyorum $scope... denetleyici hizmetteki verilere nasıl doğrudan erişir ve bunu yapmadan görünüme aktarır?
drjimmie1976

Yanıtlar:


67

Denetleyiciye zaman uyumsuz bir şey olduğunda haber vermek için Açısal vaatler kullanın .

Provoke etmek için $apply, kapsama ihtiyacınız $rootScope.$applyyoktur, onu belirli bir kapsamda veya kökte çağırmanın hiçbir farkı olmadığı için arayabilirsiniz .

Değişken okuma ile ilgili olarak, parametreler almanız daha iyi olacaktır. Ama bunu bir kapsamdan bir nesne parametresi olarak da okuyabilirsiniz, ancak ben parametre ile giderdim, bu servis arayüzünüzü çok daha net hale getirir.


Sanırım bu, AngularJS acemi şüphelerimi daha iyi çözen cevap.
SC

@Caio Cunha Dürbün geçmenin neden iyi bir fikir olmadığını açıklayabilir misiniz? Tam olarak bu sorunu yaşıyorum, $scopezaman uyumsuz bir executeSql()işlev kullanarak bir hizmete çağrı yoluyla bazı şeyler eklemek istiyorum . 3 seçeneğe bakıldığında (1) eşzamansız işlevde bir geri arama kullanın, sonra arayın $scope.$apply... bu çalışır, ancak çirkin (2) $scopeeşzamansız işleve geçtikten sonra arayın theScope.$apply()... bu da çalışır (3) bir söz kullanın. .. bunu henüz denemedim. Söz neden en iyi yoldur? Teşekkürler!
drjimmie1976

15

İşlevselliğiniz yalnızca bir denetleyiciye özgüse, bir hizmete ihtiyacınız yoksa söyleyebilirim.

Denetleyicilerin görevleri, belirli modeli manipüle etmektir, oysa bir hizmet genel görevlerle ilgilenmelidir. İşleri karıştırmak yerine bu paradigmaya bağlı kalmayı tercih ederim.

Doktorların söylediği bu

Hizmet

Açısal hizmetler, web uygulamalarında ortak olan belirli görevleri yerine getiren tekil hizmetlerdir.

Kontrolör

Angular'da, bir denetleyici, kök kapsamı hariç olmak üzere açısal Kapsam örneklerini artırmak için kullanılan bir JavaScript işlevidir (tür / sınıf).

Not: Bunun dışında, sindirmeniz gerekiyorsa, hizmetinize $ rootScope da enjekte edebilirsiniz.


2
Teşekkürler. Harika cevap. Durumuma derinlemesine girersek, mesele şu ki, bir singleton istiyorum çünkü Servis kullanıyorum. Hizmeti kullanan yalnızca bir denetleyici var, ancak bu denetleyici uygulama yaşam döngüsü boyunca birkaç kez başlatılabilir, bu nedenle Hizmetin her zaman aynı durumda olmasını gerçekten istiyorum.
SC

Neyse, arama $applyveya $digest$ rootScope ile ilgili açıklama bana tamamen mantıklı geliyor.
SC

1
Yine de test için bir Hizmete ayrı tutardım.
bluehallu

İşlevsellik bir denetleyicinin bir örneğine özgü ise , bir hizmet uygulamayı atlayabilirsiniz, ancak aksi takdirde bu örnekler arasında durum paylaşma yeteneğinden ödün vermezsiniz. Dahası, sadece bugün tek bir denetleyici türü olduğu için, yarın işlevsellikten yararlanabilecek farklı bir denetleyicinin olmayacağı anlamına gelmez. Ek olarak, bir hizmet denetleyicinin şişkinliğini önleyebilir. Yani tek bir denetleyicinin olup olmadığı değil, söz konusu olan işlevselliğin ne olduğu sorusudur.
Nick

9

Evet. $ Kapsamını, onu başlattığınızda hizmete geçirebilirsiniz. Hizmet yapıcısında kapsamı this._scope gibi bir şeye atayabilir ve ardından hizmet içindeki kapsama başvurabilirsiniz!

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, ancak, $scopehizmette bir yöntemi çağırmak ve $scopeona manuel olarak geçmek zorunda kalmamak için, söz konusu denetleyici hizmeti ne zaman enjekte ettiğinde her denetleyicinin otomatik olarak bilmesinin bir yolunu görmek isterim .
Cody

2
@Cody Dependency Injection ile çeliştiği için tavsiye etmiyorum
Coldstar

Kabul, +1 beni vurduğun için! Muhtemelen kasaplar da DIP - Gereksiz olma riskiyle söyleyebilirim.
Cody

Burada fabrikalarla hizmetleri karıştırıyorsunuz. Bu çözüm, bir hizmetten farklı bir fabrika kullanır. Temel fark, bir hizmetin bir (tekil) nesne döndürmesidir. Oysa bir fabrika, somutlaştırılabilen ( new MyFunction()) bir işlev döndürür . Soru, aramanın newbir seçenek olmadığı bir hizmetle ilgiliydi.
Karvapallo

@Karvapallo İyi nokta. Karşı nokta olarak, açısal hizmetlerin bir fabrika, hizmet ve sağlayıcıya (ng-wat) karşılık geldiğine inanıyorum.
user12121234

6

Şahsen ben $scopebir hizmete geçmenin kötü bir fikir olduğuna inanıyorum , çünkü bu bir tür döngüsel referans oluşturuyor: denetleyici hizmete bağlıdır ve hizmet denetleyicinin kapsamına bağlıdır.

İlişkiler açısından kafa karıştırıcı olmasının yanı sıra, bunun gibi şeyler çöp toplayıcının yoluna giriyor.

Tercih ettiğim yaklaşım, bir etki alanı nesnesi koymak denetleyici kapsamına ve bunu hizmete iletmektir. Bu şekilde hizmet, bir denetleyicinin içinde veya gelecekte başka bir hizmetin içinde kullanılıp kullanılmadığına bakılmaksızın çalışır.

Örneğin, hizmetin bir dizideki öğeleri itmesi ve pop yapması gerekiyorsa errors, kodum şöyle olacaktır:

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

Servis daha sonra üzerinde çalışarak kontrolör ile etkileşime girer errors. Elbette tüm dizi referansını hiçbir zaman silmemek konusunda dikkatli olmalıyım, ancak günün sonunda bu genel bir JS sorunu.

Asla yayıncılık $applyve / veya benzeri şeyler kullanmak istemem , çünkü imho iyi OO uygulamaları her zaman Açısal büyüler ne olursa olsun gölgede kalacaktır.


1
Bu kodun bununla herhangi bir farkı var mı ?:$scope.errors = []; $scope.myService = new MyService($scope.errors);
Soldeplata Saketos

@SoldeplataSaketos - Evet, öyle. errorsbağımsız yaşıyor $scope. Bu cevabın tüm amacı budur. Pls metinde verdiğim bağlantıyı kontrol edin. Şerefe.
Marco Faustinelli

1
Kodunuzu doğru $scope.errorsanlarsam, işaret ediyordur var errorsve değişken hataları, sadece başka bir işaretçi olduğu için bana gereksiz görünür. Ben ve gereksiz pervasızca olduğunu düşünebiliriz biri benzer bir durum bu kod parçasıdır: const errors = errors2 = errors3 = []; $scope.errors = errors;. Yalnızca verdiğiniz kod parçasıyla var errors = []gereksiz göründüğüne katılıyor musunuz ?
Soldeplata Saketos

Hayır değil. Kendimi kelime kelime tekrar ediyorum: errorsbağımsız yaşıyor $scope. Bir etki alanı nesnesinin ne olduğunu ve bir varatamanın ne olduğunu anlamanız gerekir . Sağladığım bağlantı yeterli değilse, pek çok başka malzeme mevcuttur.
Marco Faustinelli

Bu sadece fonksiyonun uygulanmasına bağlı olacaktır MyService(errors). Benim anlayışıma göre, hizmet parametreye (bu durumda bir işaretçi) dayalı bir günlük dizisi oluşturmalıdır. Hizmetlerin açısal olarak tekil olması benim için kötü bir model. Hizmetin gerçeklenmesi iyi programlanmışsa, diziyi dahili bir değişkende oluşturmalıdır (tekil olmaya devam etmek için). Bu nedenle, değişkeni hizmetin dışında başlatmanın bir anlamı yoktur.
Soldeplata Saketos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.