programing

서비스에서 구성 요소 보기 업데이트 트리거 - ChangeDetectorRef에 대한 공급자 없음

topblog 2023. 10. 5. 21:05
반응형

서비스에서 구성 요소 보기 업데이트 트리거 - ChangeDetectorRef에 대한 공급자 없음

서비스의 이벤트로 인해 트리거된 응용프로그램 보기를 다시 업데이트하고 싶습니다.

내 서비스 중 하나가 ChangeDetectorRef를 주입합니다.합니다.합니다.No provider for ChangeDetectorRef!.

앱 모듈에 추가해야 한다고 생각했는데 거기서 가져올 수 있는 모듈에 있다는 문서를 찾을 수 없습니다.클래스 자체를 Import Array에 추가하려고 했는데 오류가 발생했습니다.모듈의 공급자 배열에 추가하는 중에도 오류가 발생했습니다.다음은 제 서비스의 단순화 버전입니다.

import {Injectable, ChangeDetectorRef } from '@angular/core';

@Injectable()
export class MyService {
  private count: number = 0;
  constructor(private ref: ChangeDetectorRef){}

  increment() {
    this.count++;
    this.ref.detectChanges();
}

그리고 앱 모듈:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

import { MyService } from './my.service';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  providers: [ MyService ],
  booststrap: [ AppComponent ]
})
export AppModule {}

갱신하다

그 이후로 ChangeDetectorRef 사용을 제거하려고 했지만 여전히 같은 문제가 있습니다.System JS config를 업데이트한 방법이 잘못된 것 같습니다.

저는 원래 angular-cli로 앱을 만들었고, 그들이 업데이트를 하지 않았기 때문에 angular를 스스로 업데이트하려고 했습니다.Angular 2.0.0의 최종 릴리스를 통해 Angular-cli를 최신 버전의 Angular를 사용하도록 업데이트했습니다.그래서 저는 그들의 업그레이드 절차를 사용해 볼 것이고 그것이 더 잘 되기를 바랍니다.

업데이트2

웹팩/angular-cli 업데이트가 잘 되었습니다.나는 지금 Angular 2.0.0 in과 Angular-cli 1.0.0-beta14로 앱 빌드를 가지고 있습니다.브라우저에 여전히 같은 오류가 발생합니다.서비스에서 ChangeDetectorRef를 제거하려고 했지만 실제로 제거하지 못했습니다.저는 두 가지 서비스를 받았습니다.두 서비스에서 제거하면 ChangeDetectorRef를 사용하려고 했던 부분을 제외하고는 앱이 잘 로드되고 잘 작동합니다.파일 중 하나에 다시 추가하면 브라우저에서 제공자를 찾을 수 없다는 불만이 제기됩니다.

모듈로 수입하려고 했는데 모듈이 아니라서 트랜스필러가 불만을 제기합니다.모듈에 공급자를 등록하려고 했는데 공급자 속성이 없어서 트랜스필러가 불만을 제기합니다.선언 배열에 넣으려고 하면 비슷한 문제가 발생합니다.

ChangeDetectorRef여기서 사용할 수 없습니다.특정 구성요소와 해당 구성요소의 변경사항을 찾습니다.

당신의 경우에는 사용하는 것이 좋을 것 같습니다.ApplicationRef:

import {Injectable, ApplicationRef } from '@angular/core';

@Injectable()
export class MyService {
  private count: number = 0;
  constructor(private ref: ApplicationRef) {}

  increment() {
    this.count++;
    this.ref.tick();
  }
}

이 솔루션을 확인했습니다.Observables문제없이 작동합니다.

import { ApplicationRef, Injectable } from '@angular/core';
import { Observable, ReplaySubject } from "rxjs/Rx";
import * as childProcess from 'child_process';

@Injectable()
export class Reader {

    private output: ReplaySubject<string> = new ReplaySubject<string>(0);

    constructor(private ref: ApplicationRef) {
        var readerProcess = childProcess.spawn('some-process');
        readerProcess.stdout.on('data', (data) => {
            this.output.next(data.toString());
            this.ref.tick();
        });
    }

    public getOutput():Observable<string> {
        return this.output;
    }
}

이를 사용하는 구성 요소는 다음과 같습니다.

import {Component} from '@angular/core';
import { ReplaySubject, Observable } from "rxjs/Rx";

import { Reader } from './reader/reader.service';

@Component({
    selector: 'app',
    template: `
    output:
    <div>{{output}}</div>
    `
})
export class App {

    public output: string;

    constructor(private reader: Reader) {}

    ngOnInit () {
        this.reader.getOutput().subscribe((val : string) => {
            this.output = val;
        });
    }
}

서비스에서 변경을 트리거하지만 구성 요소가 언제, 어떻게 응답하는지 제어할 수 있도록 허용하는 경우에도 구독을 설정하는 것이 있습니다.

서비스에 다음을 추가합니다.EventEmitter:

changeDetectionEmitter: EventEmitter<void> = new EventEmitter<void>();

서비스에서 변경 탐지 주기를 트리거해야 할 수 있는 문제가 발생하면 다음을 수행하기만 하면 됩니다.

this.changeDetectionEmitter.emit();

이제 이 서비스를 사용하는 모든 구성 요소에서 가능한 변경 트리거를 수신해야 하는 경우 가입하고 적절하게 대응할 수 있습니다.

this.myService.changeDetectionEmitter.subscribe(
    () => {
      this.cdRef.detectChanges();
    },
    (err) => {
      // handle errors...
    }
  );

저는 이 접근방식이 마음에 듭니다. 왜냐하면 이 접근방식은 그것이 속한 구성요소로 변경 감지를 제어할 수 있게 해주지만 서비스에서 논리를 중앙 집중화할 수 있게 해주기 때문입니다.이 서비스는 UI에 대해 아무것도 알 필요가 없으며, 듣고 있는 사람에게 무언가 바뀌었다는 것을 알리는 것뿐입니다.

이미 오래 전에 이 문제를 해결해야 한다는 것을 알고 있지만, 단순히 ChangeDetectorRef를 호출되는 함수를 통해 서비스에 전달하려고 했습니다.

//myservice
import { Injectable, ChangeDetectorRef } from '@angular/core';

@Injectable()
export class MyService {
  constructor(){}

  increment(ref: ChangeDetectorRef, output: number) {
    output++;
    ref.detectChanges();
}

구성요소

import {Component} from '@angular/core';
import { MyService } from './myservice.service';

@Component({
    selector: 'app',
    template: `
    output:
    <div>{{output}}</div>
    `
})
export class App {

    public output: number;

    constructor(public ref: ChangeDetectorRef, private myService: MyService) {}

    ngOnInit () {
       this.myService.increment(this.ref,output)
    }
}

최신 버전은 이제 코어의 일부이므로 코어에 대한 참조만 가능하지만 필요한 변수를 사용하고 트릭을 수행해야 합니다.

import { TestBed } from '@angular/core/testing';
import { ChangeDetectorRef } from '@angular/core';
import { MyService } from './my.service';

describe('MyService', () => {
    beforeEach(() => TestBed.configureTestingModule({
        providers: [ChangeDetectorRef] // <--- LOOK AT ME I'M A PROVIDER!
    }));

    it('should be created', () => {
        const service: MyService = TestBed.get(MyService);
        expect(service).toBeTruthy();
    });
});

희망은 도움이 됩니다.

사용방법ApplicationRef좋은 해결책입니다.몇 가지 해결책이 더 있습니다.

  1. 사용.setTimeout

    @Injectable()
    export class MyService {
      private count: number = 0;
      constructor(){}
    
      increment() {
        setTimeout(() => this.count++, 0);
      }
    }
    
  2. 사용.Promise

    @Injectable()
    export class MyService {
      private count: number = 0;
      constructor(){}
    
      increment() {
        Promise.resolve().then(() => this.count++);
      }
    }
    

변경 탐지에 Zone.js를 사용하는 경우 두 솔루션 모두 Angular가 변경 탐지를 트리거하도록 강제합니다. 이것이 기본 방식이며 앱의 99%가 이를 사용합니다.

서비스를 구성 요소 수준의 공급업체에 추가해야 합니다.

@Component({
  // ...
  providers: [MyService]
})
export class SomeComponent {
  // ...
}

언급URL : https://stackoverflow.com/questions/39511820/trigger-update-of-component-view-from-service-no-provider-for-changedetectorre

반응형