如何在 Ionic 3 中执行多个异步操作并在完成所有操作后关闭加载器?

How to perform multiple asynchronous actions in Ionic 3 and dismiss a loader after everything is done?

我正在开发一个 Ionic 3 应用程序,它可以选择按需缓存文章内容列表。我正在使用 Storage,它使用 promises 进行操作。

我的代码如下:

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

我显然不能正常使用这里的 Observables。

问题:如何在 Ionic 3 中执行多个异步操作并在完成所有操作后关闭加载器?

您可以使用 forkjoin 轻松完成。

注:我已经提取了我的代码app.So根据你的用途改一下case.If你正在使用 RXJS 5.5.2 然后根据最新 changes here

更改 imports
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) => {  })
  }

Sampath的回答帮我找到了问题所在。我做错的是我构建 Observable 数组的方式(它在 forkJoin 中使用):在 Promise [=] 的 then 函数中推入列表 return由存储获取。

修复此问题后我的代码还包括检查项目是否存在(以避免 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 通过检查存储是否已经有密钥和实际提取获得。如果数据存在,我 return 一个空的 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));
        }
    );
}