Currently, I am in the process of developing an Ionic 3 application that offers the feature to cache a list of articles content on demand. The implementation involves utilizing Storage
which employs promises for its operations.
The code snippet I have written is as follows:
article-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());
}
article-cache-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;
}
// attempts to cache a list of articles in the cache without overwriting existing data
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;
}
code with loader
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));
}
);
The caching operation proceeds smoothly, however, the code within the then
block executes immediately (data
turns out to be undefined
).
I've also experimented with the subscribe
method, but even though the caching performs correctly, the code inside the subscribe
doesn't seem to execute as expected:
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));
}
);
I recognize that my handling of Observable
s requires refinement.
Question: How can I effectively carry out multiple asynchronous actions in Ionic 3 and dismiss a loader only after all processes are complete?