2017-11-25 278 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)); 
     } 
    ); 
} 
相关问题