2017-11-13 12 views
0

와 나는 다음이 코드 서비스 설정을 가지고 :Rxjs 초기화 자원은 한 번 뜨거운 관찰

@Injectable() 
export class StaticResourcesService { 

private resourcesTree$: Observable<any>; 

getSpecificLabel(resourceName: string, type: string): Observable<string> { 
    return this.getResources().map(resources => { 
     return jp.value(resources, `$.${resourceName}[?(@.type=="${type}")].label`); 
    }); 
    } 

private getResources(): Observable<any> { 
    if (this.resourcesTree$ != null) { 
     return this.resourcesTree$; 
    } 
    let source = this.getResourcesFilePath() // get obs<string> with a file path 
     .mergeMap(path => { 
     console.log(`static-resources path: ${path}`); 
     return this.http.get(path).map(res => res.json()); // get json obj 
     }).do(res => { 
     this.resourcesTree$ = Observable.of(res); 
     }); 
    return source; 
    } 

이 같은 변환 방법 정의 각 파이프 :이 정의를 사용

transform(resourceType: string, resourceName: string): Observable<string> { 
    return this.staticResourcesService.getSpecificLabel(resourceName, resourceType); 
    } 

및 간단한 html 페이지의 파이프 :

<div *ngFor="let item of items">{{ item?.status | staticResource:'MY_RES' | async }}</div> 

처음으로 페이지를로드하면 사용자 정의 파이프가 실행됩니다. 4 번 반복하면 (ngFor 루프 4 배) resourcesTree $에서 소스 데이터를 가져 오지 않습니다. 구독 정보가 동시에 듣고 do가 4x로 수행되므로 정상적인 동작임을 이해합니다. 그러나 내가 원했던 것은 데이터에 한 번만 액세스하고 리소스를 활용하는 최적화 된 방법입니다. 다음 3 번. 소스에서 share() 메서드를 사용하여 "hot"하게 만들려고했습니다. 하지만 제대로 작동하게 만들 수는 없습니다.

누군가 이걸 어떻게 달성 할 수 있는지 말해 줄 수 있습니까? 어쩌면 Im는 모든 틀린 Im 진짜로 어떤 제안든지 여기에서 열 n 다.

+0

가능한지 확인하십시오. 왜냐하면'getSpecificLabel'에서 당신은 기본적으로 완전히 다른 4 개의 관찰 대상을 생성하고 있기 때문입니다. 'share()'는 여기서 당신을 도울 수 없습니다. 나는 'map observable'파이프를 만들면 성취 할 수 있다고 생각하지만,'jp.value()'가 무엇을하는지에 달려있다. –

+0

jp.value는 여기서는별로 관련이 없습니다. jsonpath를 사용하여 json 객체로 특정 레이블을 검색하는 데 도움이됩니다. – thk

+0

관찰 결과에 부작용이 있습니다. 이는 잘못된 일을하는 기호 일 수 있습니다. 나는이 방법을 사용하는 것이 불가능하다고 생각한다. 당신이 정확히 무엇을 성취하려고하는지 설명해 주시겠습니까? 'item.status' 필드에 기반한 URL의 JSON 파일을 표시해야합니까? "MISSION_TYPE": [ { "유형": "PRODUCT_DELIVERY" "라벨": "Livraison PRODUIT" }, { "유형": "MANUAL_PRODUCT_DELIVERY" " –

답변

1

비동기 서비스에 대한 일반적인 패턴이 공유 자원을 주체() 또는 ReplaySubject()하는 것입니다 감사합니다. 그렇게하면 가입자를 연결하기 만하면 데이터가 도착하기를 기다리게됩니다.

예를 들어, 리소스를 조각으로 잘라 내기 때문에지도 연산자가됩니다 (이미있는 것처럼). 또한 가져 오기 신호를 보내는 방법은 이 시작되어 (관찰이 가능하므로 아직 끝나지 않았어도 상관하지 않음)입니다.

getResources()가 더 이상 외부에서 구독하지 않으므로 .do()를 .subscribe()로 바꿔야합니다.

@Injectable() 
export class StaticResourcesService { 

private resourcesTree$ = new ReplaySubject(1); 
private status = 'unloaded'; 

getSpecificLabel(resourceName: string, type: string): Observable<string> { 
    if(this.status === 'unloaded') { 
    this.status = 'loading'; 
    getResources(); 
    } 
    return resourcesTree$.map(resources => { 
    return jp.value(resources, `$.${resourceName}[?(@.type=="${type}")].label`); 
    }); 
} 

private getResources(): Observable<any> { 
    this.getResourcesFilePath() // get obs<string> with a file path 
    .mergeMap(path => { 
     console.log(`static-resources path: ${path}`); 
     return this.http.get(path).map(res => res.json()); // get json obj 
    }) 
    .subscribe(res => { 
     this.resourcesTree$.next(res); 
     this.status = 'loaded'; 
     }); 
    }