2017-11-25 280 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代碼,立即執行(dataundefined

我也曾嘗試subscribe的方法,但內subscribe代碼似乎並沒有被執行(緩存爲正確執行,雖然):

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)); 
     } 
    ); 

我顯然無法與Observable工作在這兒。

問題:如何在Ionic 3中執行多個異步操作並在完成所有操作後關閉加載程序?

回答

1

您可以使用forkjoin輕鬆做到這一點。

注:我已經提取的代碼從我case.If你使用RXJS 5.5.2然後根據最新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

試着'let'而不是'var'來看看。 – Sampath

+0

也似乎你沒有正確使用'forkjoin'。我已更新我的帖子。希望你能更好地瞭解如何使用'forkjoin'。 – Sampath

1

Sampath改變imports根據您的使用app.So改變它「我的回答幫助我找到了問題。我做錯的是我構建Observable陣列的方式(即它在forkJoin中使用):推送then函數中的Promise函數返回的存儲get。固定在此之後

我的代碼且還包括支票項存在(以避免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

我正在使用flatMap來鏈Observable從檢查存儲是否已經有密鑰獲得並且實際獲取。如果數據存在,我會返回一個空的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)); 
     } 
    ); 
} 
相關問題