2017-11-25 9 views
1

필자는 필요에 따라 기사 내용의 목록을 캐시 할 수있는 옵션 인 Ionic 3 응용 프로그램을 개발 중입니다. 그 작업에 약속을 사용하는 Storage을 사용하고 있습니다.Ionic 3에서 여러 비동기 작업을 수행하고 모든 작업이 완료된 후 로더를 닫는 방법?

내 코드는 다음과 같다 :

기사-service.ts

getArticleFullData(articleId: number) { 
    let appSettings = this.appSettingsService.getSettings(); 
    let params = this.utilsService.serializeQueryParams(appSettings); 
    let url = `${this.apiBasePath}Article/GetArticleFullData?articleId=${articleId}&${params}`; 
    this.loggingService.logInfo("Getting article full data from url " + url); 
    return this.http.get(url) 
     .map(res => res.json()); 
} 

기사 - 캐시 service.ts

// saves a single article to the cache 
private saveToCache(articleId: number): Observable<any> { 

    let key = articleId; 
    let obs = this.articleService.getArticleFullData(key); 
    obs.subscribe(data => { 
     this.storage.set(this.GetArticleFullKey(key), data as ArticleFullData); 
    }, 
     err => { 
      this.loggingService.logError("Failed to cache data for article: " + key); 
     } 
    ); 

    return obs; 
} 

// tries to cache a list of article in the cache 
// avoids overwriting the data, if exists 
public saveArticleDataToCache(articles: ArticleBriefData[]): Observable<{}[]> { 

    var obsArray = []; 
    for (let article of articles) { 
     let key = this.GetArticleFullKey(article.ArticleId); 
     this.storage.get(key) 
      .then(data => { 
       console.log("Storage data for article " + key, data); 

       if (!data) { 
        obsArray.push(this.saveToCache(article.ArticleId)); 
       } 
      }) 
      .catch(err => { 
       this.loggingService.logError("Failed to check storage for key " + key, err); 
      }); 
    } 

    var ret = Observable.forkJoin(obsArray); 
    return ret; 
} 

코드가 포함 로더

this.loadingCtrl.create({ content: "Caching data. Please wait..." }); 
    this.loadingCtrl.present(); 

    var all = this.articleCacheService.saveArticleDataToCache(this.articles); 
    var subscr = all 
     .toPromise() 
     .then(data => { 
      console.log("All data: ", data); 
      this.loadingCtrl.dismiss(); 
      this.loggingService.logInfo("Successfully cached articles "); 
     }) 
     .catch(err => { 
      this.loadingCtrl.dismiss(); 
      this.loggingService.logError("Failed to cache data: ", JSON.stringify(err)); 
     } 
    ); 

는 캐싱 프로세스가 제대로 실행하지만 then 코드는

가 나는 또한 subscribe 접근 방식을 시도했다 (dataundefined입니다) 즉시 실행되지만 subscribe 내 코드는 캐싱은 (실행하지 않는 것 제대로,하지만) 실행 : 나는 분명히 Observable 제대로 작동하고 있지 않다

var all = this.articleCacheService.saveArticleDataToCache(this.articles); 
    var subscr = all 
     .subscribe(data => { 
      console.log("All data: ", data); 

      this.loadingCtrl.dismiss(); 
      this.loggingService.logInfo("Successfully cached articles "); 
     }, 
     err => { 
      this.loadingCtrl.dismiss(); 
      this.loggingService.logError("Failed to cache data: ", JSON.stringify(err)); 
     } 
    ); 

것은 여기에요.

질문 : Ionic 3에서 여러 비동기 작업을 수행하고 모든 작업이 완료된 후 로더를 닫는 방법?

답변

1

forkjoin을 사용하면 쉽게 할 수 있습니다.

참고 : 난에서 코드를 추출한 내 당신이 다음 changes here

import { Observable } from "rxjs/Observable"; 
import 'rxjs/add/observable/forkJoin' 

let myTopicApi = this.getMytopic(); 
let myarticlApi = this.getMyArticles(); 
let myPicksAPi = this.getMyPicks(); 
Observable.forkJoin([myTopicApi, myarticlApi, myPicksAPi]) 
    .subscribe(res => { 
    this.arrangeMytopics(res[0]); 
    this.arrangeMyArticles(res[1]); 
    this.arrangeMyPicks(res[2]); 
    if (loading) { loading.dismiss(); loading = null; }//here you can dismiss your loader 
    }, 
    error => { if (loading) { loading.dismiss(); loading = null; }//here you can dismiss your loader }, 
() => { }); 

getMytopic() { 
    return this.topicSer.getMyTopics().map((res: any) => res.json()).map((res: any) => res = res.categories) 
     .catch((err: any) => { }) 
    } 
+0

감사합니다. 나는'rxjs 5.4.0'을 사용하고 있습니다. 내 코드는 이미'forkJoin'을 사용하고 있지만 예상대로 작동하지 않습니다. 그것은'getArticleFullData'가하는 일과 관련이 있을지 모르지만, 무엇이 잘못되었는지를 알 수는 없습니다 (그 함수의 코드도 추가했습니다). – Alexei

+0

'var' 대신'let'을 시도해보십시오. – Sampath

+0

또한 'forkjoin'을 제대로 사용하지 않은 것으로 보입니다. 내 게시물을 업데이트했습니다. 'forkjoin'을 어떻게 사용하는지 더 좋은 아이디어를 얻을 수 있기를 바랍니다. – Sampath

1

Sampath 최신에 따라 imports을 변경 RXJS 5.5.2를 사용되었다 네 app.So '사용자의 용도에 따라 변경 나는 그 문제를 찾는데 도움이되었다. 내가 잘못하고있는 것은 내가 구성된 Observable 어레이 (forkJoin에 사용됨)입니다. then의 목록 내에서 밀어 넣는 것은 Promise의 저장소에서 반환됩니다.

내 코드이 고정 후 그도 (HTTP 호출 및 재설정 저장 데이터를 피하기 위해) 항목이 있는지 검사를 포함

기사-service.ts

getArticleFullData(articleId: number) { 
    let appSettings = this.appSettingsService.getSettings(); 
    let params = this.utilsService.serializeQueryParams(appSettings); 
    let url = `${this.apiBasePath}Article/GetArticleFullData?articleId=${articleId}&${params}`; 
    return this.http.get(url) 
     .map(res => res.json()); 
} 

기사 캐시를 -service.ts

은 저장 장치에 이미 키가 있는지 확인한 후 사용합니다. 실제 가져 오기 데이터가있는 경우 실제로 처리를 취소하려면 빈 Observable을 반환합니다.

private saveToCache(articleId: number): Observable<any> { 

    let key = this.GetArticleFullKey(articleId); 

    let storageObs = Observable.fromPromise(this.storage.get(key)); 
    let getArticleObs = this.articleService.getArticleFullData(articleId); 

    let obs = storageObs.flatMap(data => { 
     if (!data) 
      return getArticleObs; 
     else 
      return Observable.of(null); 
    }); 

    obs.subscribe(data => { 

     if (data) 
      this.storage.set(key, data as ArticleFullData); 
    }, 
     err => { 
      this.loggingService.logError("Failed to cache data for article: " + articleId); 
     } 
    ); 

    return obs; 
} 

public saveArticleDataToCache(articles: ArticleBriefData[]): Observable<{}[]> { 

    let obsArray = []; 
    for (let article of articles) { 

     let obs = this.saveToCache(article.ArticleId); 
     obsArray.push(obs); 
    } 

    let ret = Observable.forkJoin(obsArray); 
    return ret; 
} 

실제 가입 빠른 답변

onCacheRefresh() { 
    // articles are not loaded for some reason 
    if (!this.articles) 
     return; 

    this.loadingCtrl.create({ content: "Caching data. Please wait..." }); 
    this.loadingCtrl.present(); 

    let all = this.articleCacheService.saveArticleDataToCache(this.articles); 
    let subscr = all 
     .subscribe(data => { 
      console.log("All data: ", data); 

      this.loadingCtrl.dismiss(); 
      this.loggingService.logInfo("Successfully cached articles "); 
     }, 
     err => { 
      this.loadingCtrl.dismiss(); 
      this.loggingService.logError("Failed to cache data: ", JSON.stringify(err)); 
     } 
    ); 
}