Uygulama Angular 2'de başladığında bir hizmet nasıl çalıştırılır


97

Bir servis SocketService oluşturdum, temelde uygulamanın portu dinlemesine izin vermek için soketi başlatıyor. Bu hizmet aynı zamanda bazı bileşenlerle etkileşim halindedir.

// socket.service.ts

export class SocketService {
    constructor() {
        // Initializes the socket
    }
    ...
}

SocketService yapıcısındaki () kodun yalnızca bir bileşen SocketService kullandığında çalışmaya başladığını biliyorum.

Ve genellikle app.ts içindeki kod şöyle görünür:

// app.ts

import {SocketService} from './socket.service';
...
class App {
    constructor () {}
}
bootstrap(App, [SocketService]);

Ancak, uygulama başladığında bu hizmetin çalışmasını istiyorum. Bu yüzden bir numara yaptım, sadece private _socketService: SocketServiceApp yapıcısını () ekleyin . Şimdi kodlar şöyle görünüyor:

// app.ts (yeni)

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {}
}
bootstrap(App, [SocketService]);

Şimdi çalışıyor. Sorun bazen SocketService'in constructor ()ındaki kodların bazen çalıştırılmamasıdır. Peki bunu nasıl doğru yapmalıyım? Teşekkürler


Bu kılavuz bana yardımcı oldu: angular.io/docs/ts/latest/tutorial/...
Marian07

Yanıtlar:


130

Stuart'ın cevabı doğru yönü gösteriyor, ancak APP_INITIALIZER'da bilgi bulmak kolay değil. Kısa versiyon, onu diğer uygulama kodlarınızdan herhangi biri çalışmadan önce başlatma kodunu çalıştırmak için kullanabilmenizdir. Bir süre aradım ve burada ve burada açıklamalar buldum , web'den kaybolmaları durumunda özetleyeceğim.

APP_INITIALIZER, açısal / çekirdek olarak tanımlanır. Bunu app.module.ts dosyanıza böyle eklersiniz.

import { APP_INITIALIZER } from '@angular/core';

APP_INITIALIZER, ApplicationInitStatus hizmetine başvuran bir OpaqueToken (veya Angular 4'ten beri bir InjectionToken). ApplicationInitStatus bir çoklu sağlayıcıdır . Birden çok bağımlılığı destekler ve sağlayıcı listenizde birden çok kez kullanabilirsiniz. Bu şekilde kullanılır.

@NgModule({
  providers: [
    DictionaryService,
    {
      provide: APP_INITIALIZER,
      useFactory: (ds: DictionaryService) => () => return ds.load(),
      deps: [DictionaryService],
      multi: true
    }]
})
export class AppModule { }

Bu sağlayıcı bildirimi, ApplicationInitStatus sınıfına DictionaryService.load () yöntemini çalıştırmasını söyler. load () bir söz verir ve ApplicationInitStatus söz çözülene kadar uygulama başlangıcını engeller. Load () işlevi bu şekilde tanımlanır.

load(): Promise<any> {
  return this.dataService.getDiscardReasons()
  .toPromise()
  .then(
    data => {
      this.dictionaries.set("DISCARD_REASONS",data);
    }
  )
}

Önce sözlüğün yükleneceği ve uygulamanın diğer bölümlerinin güvenli bir şekilde buna bağlı olabileceği şekilde ayarlayın.

Düzenleme: Bunun, load () yöntemi ne kadar uzun sürerse sürsün uygulamanız için ön yükleme süresini artıracağını unutmayın. Bundan kaçınmak istiyorsanız, bunun yerine rotanızda bir çözücü kullanabilirsiniz .


Bunun için teşekkürler ... çok yardımcı oldu
Gaurav Joshi

5
Kabul edilen cevap bu olmalıdır. Geçerli olan, bir kurucudan bir inityönteme yalnızca bir satır kod taşır . Yapıcıların gerçekten olabildiğince basit tutulması gerekirken, bu düşünce tek başına onu uygun bir çözüm yapmaz. Kullanıyor APP_INITIALIZER.
JP ten Berge

OP'nin problemini çözdüğü için seçilen cevabın yanlış olduğunu düşünmüyorum. AMA , bazı kütüphanelerin geliştirilmesinde benzer bir problemim olduğu için, bu cevabın mükemmel bir şekilde uyacağı başka bir soru daha açtım .
Machado

Bunu yapmanın en iyi yolu
Renil Babu

58

Yapıcınızdaki mantığı SocketServicebunun yerine bir yönteme taşıyın ve ardından ana bileşenin yapıcısında veyangOnInit

SocketService

export class SocketService{
    init(){
        // Startup logic here
    }
}

Uygulama

import {SocketService} from './socket.service';
...
class App {
    constructor (private _socketService: SocketService) {
        _socketService.init();
    }
}
bootstrap(App, [SocketService]);

1
yapıcı yerine yöntemin arkasındaki mantık ne yapıyor anlamıyorum bunu açıklar mısınız, yöntemde mantık yapmanın avantajı nedir?
Pardeep Jain

1
Daha temiz bir yaklaşım
imho

12
Ekstra mantık eklemeniz gerektiğinde ngOnInit kancasını kullanarak kurucular olabildiğince basit olmalıdır (normalde sadece enjeksiyon noktaları).
Sergio

1
Takımın aklına gelmeyen bir şey daha… Angular 4 üzerinde çalıştıkça Aurelia çerçevesinin ne kadar zekice inşa edildiğini anlıyorum. Sadece bir dekoratör ekleyerek kutudan çıktığı anda tüm bu olasılıklara sahiptir. Bu adamlar ne yaptıklarını biliyor.
Joel Hernandez

1
@CodyBugstein Kullanım durumunuza bağlıdır. Sadece ateşle ve unut ise, asenkron yöntemi çağırın. Sonucu beklemeniz gerekiyorsa Promise, init()yönteminizden bir dönebilir ve ardından gerektiği gibi zincirleyebilirsiniz. Durum ne olursa olsun o olabilir yapılabilir, ancak muhtemelen zor olacak ve ayrıntıları halletmek size kalmış olacak. Daha fazla yardıma ihtiyacınız olursa, her zaman sorununuzun ayrıntılarını içeren bir soru gönderebilirsiniz ve topluluk size yardımcı olmaktan memnuniyet duyar.
SnareChops


1

Hizmet oluşturucu oluşturmayı deneyin ve ardından bileşeninizin ngOnInit () 'ini çağırın.

  • Servis Modülü

 export class SocketService {
    constructor() { }
        getData() {
            //your code Logic
        }
}

  • Bileşen

export class AppComponent {
    public record;  
    constructor(private SocketService: DataService){ }
    ngOnInit() {        
        this.SocketService.getData()
        .subscribe((data:any[]) => {
            this.record = data;
        });   
  }  
}       

Bu yardımcı olur umarım.


1
@Hongbo çalıştırmak için hizmet istediğinde değil hizmetini kullanıyor belirli bir bileşende uygulama başladığında,
Jarod Moser

Bu gerçekten basit cevap benim için çalıştı. Basit cevapları seviyorum. Teşekkürler.
Aggie Jon, 87
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.