해결하고자 하는 문제가 있는데 자바스크립트의 비동기식 처리에 익숙하지 않아서 방법을 모르겠습니다.
일단 코드를 간단히 정리하면 이렇습니다.
class A { foo: string; bar: string; isFetched = false; async getFoo() : Promise<string> { if (this.foo || this.isFetched) { return this.foo; } await A.fetch(this); console.log('foo =', this.foo); return this.foo; } async getBar() : Promise<string> { if (this.bar || this.isFetched) { return this.bar; } await A.fetch(this); console.log('bar =', this.bar); return this.bar; } static async fetch(a: A) : Promise<A> { console.log('calling fetch'); await new Promise(resolve => setTimeout(resolve, 1000)); a.foo = 'hello'; a.bar = 'world'; a.isFetched = true; console.log('returning...'); return a; } } const x = new A(); Promise.all([ x.getFoo(), x.getBar() ]);
정리하면 object의 두 field 의 value는 필요할때 on-demand로 저장해서 사용하고 싶습니다.
fetch는 cost가 좀 있는 작업인데 대신 한번 하면 두 값을 모두 가져올수 있어요.
문제는 getter 가 언제 어떻게 불릴지 모른다는 겁니다.
근데 저렇게 그냥 각각 요청해버리면 비동기 특성상 fetch() 가 각각 두번 불리게 되는데 이걸 방지할수 있을까요?
애초에 Node.js 를 쓰는환경에서 저런 패턴으로는 답이 없는건지...
====
답변 주신대로 Promise를 field로 가지고 있는 것으로 일단 수정해봤습니다.
이렇게 하려니 isFetched 가 필요 없고 이 promise가 대신할 수 있곘네요.
감사합니다.
class A { foo: string; bar: string; fetcher?: Promise<A>; async getFoo() : Promise<string> { if (this.foo) { return this.foo; } if (!this.fetcher) { this.fetcher = A.fetch(this); } await this.fetcher; console.log('foo =', this.foo); return this.foo; } async getBar() : Promise<string> { if (this.bar) { return this.bar; } if (!this.fetcher) { this.fetcher = A.fetch(this); } await this.fetcher; console.log('bar =', this.bar); return this.bar; } static async fetch(a: A) : Promise<A> { console.log('calling fetch'); await new Promise(resolve => setTimeout(resolve, 1000)); a.foo = 'hello'; a.bar = 'world'; console.log('returning...'); return a; } } const x = new A(); Promise.all([ x.getFoo(), x.getBar() ]);
대기 끝나고 나서 값이 fetch 되어있으면 그거 쓰고, 에러나서 fetch 가 안되어 있으면 다시 호출하고...?
저라면 promise 자체를 인스턴스에서 가지고 있을 것 같네요.
class A {
promise: Promise<{ foo: string, bar: string }> | undefined = undefined;
async getFoo() : Promise<string> {
if (promise === undefined) {
promise = new Promise....
}
return (await promise).foo
}
....
고민을 좀 해보겠습니다.
힌트 감사드립니다.
Fetch는 저 두 field 를 구하는 Data Access 입니다. DB query 이거나 API request 이거나 암튼 cost가 있는건데
1. 필요 없으면 안하고 싶다
2. 둘 중 하나라도 필요하면 한번만 하고 싶다
입니다.
이게 예제는 두개인데 더 있는지라 각각 하면 성능이 염려되고
그러느니 그냥 1을 포기하고 A를 만들때 항상 fetch 한번만 하는게 더 나은 상황이 되어서요..
혹시 Promise를 더 파봐야할까요?
Promise로 간단히 처리 할 수 있군요!
저는 observer 패턴을 사용해서 개선해 볼 생각이었습니다만, Promise도 좋은것 같네요!
양쪽 다 컨트롤이 가능하신 상황이라면 client 보단 server쪽에서 캐싱해서 값을 내려주는게 제일 좋을거 같아요.
client에서 get을 호출하는 타이밍을 잡지 못하는 상황이라면 더더욱.
그게 아니라면 업데이트 하신 방법이 최선이겠네요..
그래서 말씀하신 방법을 적용하기 힘든 상황이었습니다.
이해 하셨겠지만, 제가 client / server 라고 칭한건 frontend / backend가 아니라 call하는 파트 / call을 받고 response해주는 파트를 이야기 드린거였습니다.
전에 글 쓰신거 보니 캐나다 계신것 같습니다 :)
타지에서 고생 많으십니다. 화이팅!