如何在Ionic 3中执行多个异步操作并在完成所有操作后关闭加载程序?
问题描述:
我开发了一个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
代码,立即执行(data
是undefined
)
我也曾尝试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中执行多个异步操作并在完成所有操作后关闭加载程序?
答
您可以使用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) => { })
}
答
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));
}
);
}
感谢您的快速答复。我正在使用'rxjs 5.4.0'。我的代码已经使用'forkJoin',但它不能按预期工作。它可能与'getArticleFullData'的作用有关,但我无法弄清楚什么是错误的(我也添加了该函数的代码)。 – Alexei
试着'let'而不是'var'来看看。 – Sampath
也似乎你没有正确使用'forkjoin'。我已更新我的帖子。希望你能更好地了解如何使用'forkjoin'。 – Sampath