Angular 'ngOnInit'의 비동기/대기
저는 현재 Angular의 respons를 대체하는 것에 대한 찬성 'n'의 단점을 평가하고 있습니다.RxJS'Observable
Promise
사할수있록도용록을 사용할 수 .async
그리고.await
보다 직관적인 코드 스타일을 얻을 수 있습니다.
인 시나리오 중 는 일적인시중하다같다습니음과나는반 내에서 를 로드하는 입니다.ngOnInit
.사용.Observables
사용자:
ngOnInit () {
this.service.getData().subscribe(data => {
this.data = this.modifyMyData(data);
});
}
가 품반시를 때.Promise
getData()
대신에, 그리고 사용합니다.async
그리고.await
다음과 같습니다.
async ngOnInit () {
const data = await this.service.getData();
this.data = this.modifyMyData(data);
}
자, 분명히, 앵글은 그것을 "알지" 못할 것입니다.ngOnInit
가 되었습니다.async
저는 이것이 문제가 아니라고 생각합니다.내 앱은 여전히 예전처럼 작동합니다.▁the▁는▁i▁but▁when을▁look봤하지.OnInit
인터페이스, 함수는 분명히 선언될 수 있는 방식으로 선언되지 않았습니다.async
:
ngOnInit(): void;
그래서 -- 결론은:제가 여기서 하는 일이 합리적인가요?아니면 제가 예상치 못한 문제에 부딪힐까요?
그것은 당신이 전에 가졌던 것과 다르지 않습니다.ngOnInit
약속을 반환하고 발신자가 해당 약속을 무시합니다.이는 메서드가 계속 진행되기 전에 호출자가 메서드의 모든 작업이 완료될 때까지 기다리지 않음을 의미합니다.되기 전에 시작될 수 합니다.this.data
설정됩니다.
그것은 당신이 전에 가졌던 것과 같은 상황입니다.호출자는 가입이 완료될 때까지 기다리지 않고 앱을 시작할 수 있습니다.this.data
이미 채워졌습니다.사용자의 의견이 다음에 의존하는 경우data
그러면 당신은 아마도 어떤 종류의ngIf
액세스할 수 없도록 설정합니다.
저는 개인적으로 당신이 그 영향을 알고 있는 한 그것을 어색하거나 나쁜 관행으로 보지 않습니다. 하만지그, 그.ngIf
지루할 수 있습니다(어느 쪽이든 필요합니다).저는 개인적으로 이러한 상황을 피할 수 있도록 경로 확인기를 사용하는 것으로 이동했습니다.경로 탐색이 완료되기 전에 데이터가 로드되고 보기가 로드되기 전에 데이터를 사용할 수 있는지 알 수 있습니다.
이제 Angular는 ngOnInit가 비동기화되었다는 것을 "알지" 못할 것입니다.저는 이것이 문제가 아니라고 생각합니다.내 앱은 여전히 예전처럼 작동합니다.
의미론적으로는 컴파일이 잘 되고 예상대로 실행되지만 쓰기의 편리함async / wait
오류 처리 비용이 들기 때문에 피해야 한다고 생각합니다.
무슨 일이 일어나는지 봅시다.
약속이 거부될 경우 발생하는 현상:
public ngOnInit() {
const p = new Promise((resolver, reject) => reject(-1));
}
위에서 다음 스택 추적을 생성합니다.
core.js:6014 ERROR Error: Uncaught (in promise): -1
at resolvePromise (zone-evergreen.js:797) [angular]
at :4200/polyfills.js:3942:17 [angular]
at new ZoneAwarePromise (zone-evergreen.js:876) [angular]
at ExampleComponent.ngOnInit (example.component.ts:44) [angular]
.....
처리되지 않은 오류가 다음에 의해 트리거되었음을 명확하게 알 수 있습니다.ngOnInit
그리고 어떤 소스 코드 파일이 악성 코드 줄을 찾는지도 확인합니다.
가 시용발현상는을 사용하면 ?async/wait
, 거부 즉, 거:
public async ngOnInit() {
const p = await new Promise((resolver, reject) => reject());
}
위에서 다음 스택 추적을 생성합니다.
core.js:6014 ERROR Error: Uncaught (in promise):
at resolvePromise (zone-evergreen.js:797) [angular]
at :4200/polyfills.js:3942:17 [angular]
at rejected (tslib.es6.js:71) [angular]
at Object.onInvoke (core.js:39699) [angular]
at :4200/polyfills.js:4090:36 [angular]
at Object.onInvokeTask (core.js:39680) [angular]
at drainMicroTaskQueue (zone-evergreen.js:559) [<root>]
무슨 일입니까?스택 추적이 구성 요소 외부에 있기 때문에 단서가 없습니다.
그래도, 당신은 약속을 사용하고 싶어하고 단지 사용을 피하려고 하지 않을 수도 있습니다.async / wait
한번 setTimeout()
.
public ngOnInit() {
const p = new Promise((resolver, reject) => {
setTimeout(() => reject(), 1000);
});
}
다음 스택 추적을 가져옵니다.
core.js:6014 ERROR Error: Uncaught (in promise): [object Undefined]
at resolvePromise (zone-evergreen.js:797) [angular]
at :4200/polyfills.js:3942:17 [angular]
at :4200/app-module.js:21450:30 [angular]
at Object.onInvokeTask (core.js:39680) [angular]
at timer (zone-evergreen.js:2650) [<root>]
다시 말하지만, 우리는 여기서 맥락을 잃었고 버그를 수정하기 위해 어디로 가야 할지 모릅니다.
관찰 가능한 항목은 오류 처리의 부작용이 동일하지만 일반적으로 오류 메시지의 품질이 더 우수합니다.다른 사용자가 사용하는 경우throwError(new Error())
Error 객체는 스택 추적을 포함할 것이며, 만약 당신이 그것을 사용한다면.HttpModule
오류 개체는 일반적으로 요청에 대해 알려주는 Http 응답 개체입니다.
그래서 여기 이야기의 교훈은: 실수를 포착하고, 사용할 수 있을 때와 사용하지 않을 때 관찰할 수 있는 것을 사용하는 것입니다.async ngOnInit()
그것은 다시 찾아 고치기 어려운 벌레로 여러분을 괴롭힐 것이기 때문입니다.
즉시 호출된 함수 표현식의 단점은 무엇인지 궁금합니다.
ngOnInit () {
(async () => {
const data = await this.service.getData();
this.data = this.modifyMyData(data);
})();
}
그것이 선언하지 않고 작동할 수 있는 유일한 방법입니다.ngOnInit()
한 사람으로서async
를 수행
ngOnInit() 내부에서 시도 캐치를 사용했습니다.
async ngOnInit() {
try {
const user = await userService.getUser();
} catch (error) {
console.error(error);
}
}
그러면 더 설명적인 오류가 발생하고 버그가 있는 위치를 찾을 수 있습니다.
ngOnInit
약속이 완료될 때까지 기다리지 않습니다.다음과 같이 wait를 사용하고 싶은 경우 비동기 기능으로 만들 수 있습니다.
import { take } from 'rxjs/operators';
async ngOnInit(): Promise<any> {
const data = await firstValueFrom(this.service.getData());
this.data = this.modifyMyData(data);
}
그러나 사용 중인 경우ngOnInit
생성자가 함수가 완료될 때까지 기다리는 대신 기본적으로 다음과 같은 작업을 수행합니다.
import { take } from 'rxjs/operators';
constructor() {
firstValueFrom(this.service.getData())
.then((data => {;
this.data = this.modifyMyData(data);
});
}
비동기 기능을 실행하지만 완료될 때까지 기다리지 않습니다.어떤 때는 완료되고 어떤 때는 완료되지 않는 것을 알아차린다면, 그것은 정말로 여러분의 기능의 타이밍에 달려있습니다.
이 게시물의 아이디어를 사용하면 기본적으로 밖으로 도망갈 수 있습니다.zone.js
.NgZone
에는 포하않이 포함되지 .scheduleMacroTask
,그렇지만zone.js
이미 각도로 가져왔습니다.
해결책
import { isObservable, Observable } from 'rxjs';
import { take } from 'rxjs/operators';
declare const Zone: any;
async waitFor<T>(prom: Promise<T> | Observable<T>): Promise<T> {
if (isObservable(prom)) {
prom = firstValueFrom(prom);
}
const macroTask = Zone.current
.scheduleMacroTask(
`WAITFOR-${Math.random()}`,
() => { },
{},
() => { }
);
return prom.then((p: T) => {
macroTask.invoke();
return p;
});
}
으로 이 을 저의 저는개인이기제안넣다니었에 .core.module.ts
아무데나 놓을 수는 있지만 말입니다.
다음과 같이 사용합니다.
constructor(private cm: CoreModule) {
const p = this.service.getData();
this.post = this.cm.waitFor(p);
}
또한 관찰 가능한 상태로 유지하기 위해 isBrowser를 확인하거나 결과를 기다릴 수도 있습니다.
반대로, 당신은 또한 가져올 수 있습니다.angular-zen
이 게시물처럼 사용하십시오. 필요 이상으로 많이 수입하게 됩니다.
J
업데이트: 2/26/22 - 현재 사용firstValueFrom
이래.toPromise()
감가상각됩니다.
함수 rxjs를 사용할 수 .of
.
of(this.service.getData());
약속을 관찰 가능한 시퀀스로 변환합니다.
이 질문에 대한 정답은 Angular의 Resolver 기능을 사용하는 것입니다.Resolve를 사용하면 렌더링하라는 지시가 있을 때까지 구성 요소가 렌더링되지 않습니다.
문서에서:
클래스가 데이터 공급자로 구현할 수 있는 인터페이스입니다.데이터 공급자 클래스를 라우터와 함께 사용하여 탐색 중에 데이터를 확인할 수 있습니다.인터페이스는 탐색이 시작될 때 호출되는 Resolve() 메서드를 정의합니다.라우터는 경로가 최종적으로 활성화되기 전에 데이터가 확인될 때까지 기다립니다.
저는 이것을 조금 다르게 할 것입니다, 당신은 당신의 html 템플릿을 보여주지 않지만, 저는 당신이 그 안에서 데이터, 즉, 무엇인가를 하고 있다고 생각합니다.
<p> {{ data.Name }}</p> <!-- or whatever -->
비동기 파이프를 사용하지 않는 이유가 있습니까? 즉,
<p> {{ (data$ | async).Name }}</p>
또는
<p *ngIf="(data$ | async) as data"> {{ data.name }} </p>
그리고 당신의 안에서ngOnInit
:
data$: Observable<any>; //change to your data structure
ngOnInit () {
this.data$ = this.service.getData().pipe(
map(data => this.modifyMyData(data))
);
}
언급URL : https://stackoverflow.com/questions/56092083/async-await-in-angular-ngoninit
'programing' 카테고리의 다른 글
cURL에서 HTTP 헤더가 있는 API 키 전달 (0) | 2023.08.17 |
---|---|
부트스트랩 입력 포커스 파란색 표시 변경 (0) | 2023.08.12 |
모든 하위 요소 가져오기 (0) | 2023.08.12 |
"git checkout"과 "git checkout"의 차이 -- (0) | 2023.08.12 |
저장() 전에 스프링 데이터 JPA가 SELECT를 수행하지 않도록 하려면 어떻게 해야 합니까? (0) | 2023.08.12 |