离子3 - 更新与异步数据可观察 [英] Ionic 3 - Update Observable with Asynchronous Data
问题描述
对于社交媒体应用程序,我使用 AngularFire 2
来收集由其ID标识的Feed对象的集合。一旦这些ID中的每一个都从存储实际提要对象的数据库中提取相关数据,我希望用这个信息更新 feedCards
Observable对象,这样我就可以异步显示我的HTML中的feed对象的集合。这是一个相当混乱的事件链,所以让我总结一下。
循序渐进的方法
$ b在在
$ b
displayFeed()
> NavControllerMain
页面上加载feed
组件。
displayFeed()
获取twiner
项目,这本质上是一个用户配置文件项目,用户配置文件在userProfile
变量中。
加载用户配置文件后,全局 feedCards
Observable设置为等于
loadFeed()
,它返回一个Observable数组。loadFeed()
使用userProfile
全局对象的id
值来加载这个快照然后被订阅,并且本地feed
变量被设置为等于结果列表的
loadFeed
返回一个Observable对象,其中feed 参考列表由每个提要引用包含的数据映射。
object
pullFeedData(number)
引用一个提要对象并返回一个
有用的功能
alert(JSON.stringify(feedData));
c $ c> feed
> 基本上就是其他的东西。
无效
- / blockquote>
feed.map(...
不会更新提要数组,因为pullFeedData(number)
异步返回feedData
。因此,alert(JSON.stringify(data));
displayFeed()
alerts[
$ b
代码
feed.ts
userProfile:any;
feed:FirebaseListObservable< any>;
feedData:FirebaseObjectObservable< any>;
feedCards:Observable< any []>;
构造函数(公共数据库:AngularFireDatabase,公共nativeStorage:NativeStorage){}
$ b displayFeed():void {
this.nativeStorage.getItem('twiner') ((res)=> {
this.userProfile = res;
this.feedCards = this.loadFeed();
this.feedCards.subscribe((data)=> {
alert(JSON.stringify(data));
})
});
}
loadFeed():Observable< any []> {
var feed;
this.feed = this.db.list('/ twiners /'+ this.userProfile.id +'/ feed',{preserveSnapshot:true}); (快照)=> {feed = snapshots});
this.feed.subscribe((snapshots)=> {feed = snapshots}); ($ snapshot)=> {
this.pullFeedData(snapshot.val())。subscribe((feedData)=> {
alert( JSON.stringify(feedData));
return feedData;
});
}))。delay(1000);
pullFeedData(twine:number):any {
return this.db.object('/ twines /'+ twine,{preserveSnapshot:true});
feed.html
< ion-content fullscreen scroll =trueoverflow-scroll =true>
< ion-card * ngIf =feedCards | async> feedCards exists< / ion-card>
< twine-feed-card * ngFor =let feedCards | async
[data] =feedCard
>< / twine-feed-card>
< / ion-content>
小结
feed.map
不会更新feed
,因为新的数据正在被异步拉。
谢谢!
解决方案订阅的observable不返回值。它返回一个
订阅
对象,您可以稍后使用它来取消订阅。
您可以使用
switchMap
在呼叫期间从第一个可观察到切换到下一个并返回值。
也可以使用forkJoin
,它将调用一个observables数组,并等待数组值返回到订阅中。
首先声明feed 类变量作为
Observable
。feed:Observable< any>然后在你的
loadFeed()中:Observable< any []> $ / pre>
/ code>
return this.feed.switchMap((snapshots)=> {
let observableArray = [];
snapshots.forEach(snapshot => {
observableArray.push(this.pullFeedData(snapshot.val()));
});
return Observable .forkJoin(observableArray)
})
For a social media app, I have a collection of feed objects referenced by their IDs using
AngularFire 2
. Once each of these IDs has its relevant data pulled from the database that stores the actual feed objects, I wish to update thefeedCards
Observable object with this information so I can asynchronously display a collection of feed objects in my HTML. It's a pretty confusing chain of events, so let me summarize it for you.Step-by-step Approach
displayFeed()
is invoked right before theNavController
loads thefeed
component on theMain
page.displayFeed()
gets thetwiner
item, which is essentially a user profile item, and then stores the user profile in theuserProfile
variable.- Once the user profile is loaded, the global
feedCards
Observable is set equal toloadFeed()
, which returns an Observable array.loadFeed()
uses theid
value of theuserProfile
global object to load the list of feed references stored in the user profile.- This snapshot is then subscribed to and the local
feed
variable is set equal to the result list of feed references.loadFeed
returns an Observable object in which thefeed
reference list is mapped by the data each feed reference contains.pullFeedData(number)
takes in a reference to a feed object and returns an observable with the associated feed data.
What Works
alert(JSON.stringify(feedData));
alerts the correctfeed
objectBasically everything else.
What Doesn't Work
feed.map(...
does not update the feed array becausepullFeedData(number)
pulls and returns thefeedData
asynchronously. Thus,alert(JSON.stringify(data));
indisplayFeed()
alerts[null]
.Code
feed.ts
userProfile:any; feed: FirebaseListObservable<any>; feedData: FirebaseObjectObservable<any>; feedCards: Observable<any[]>; constructor(public db: AngularFireDatabase, public nativeStorage: NativeStorage) {} displayFeed():void { this.nativeStorage.getItem('twiner').then((res) => { this.userProfile = res; this.feedCards = this.loadFeed(); this.feedCards.subscribe((data)=>{ alert(JSON.stringify(data)); }) }); } loadFeed():Observable<any[]> { var feed; this.feed = this.db.list('/twiners/' + this.userProfile.id + '/feed', { preserveSnapshot: true }); this.feed.subscribe((snapshots)=>{feed = snapshots}); return Observable.of(feed.map((snapshot) => { this.pullFeedData(snapshot.val()).subscribe((feedData)=>{ alert(JSON.stringify(feedData)); return feedData; }); })).delay(1000); } pullFeedData(twine:number):any { return this.db.object('/twines/' + twine, { preserveSnapshot: true }); }
feed.html
<ion-content fullscreen scroll="true" overflow-scroll="true"> <ion-card *ngIf="feedCards | async">feedCards exist</ion-card> <twine-feed-card *ngFor="let feedCard of feedCards | async" [data]="feedCard" ></twine-feed-card> </ion-content>
Summary
feed.map
does not updatefeed
with feed objects because the new data is being pulled asynchronously. I need a fix for this.Thank you!
解决方案A subscribed observable does not return a value. It returns a
Subscription
object which you can use to unsubscribe later.You can use
switchMap
to switch from first observable to the next during the call and return the values. Also you can useforkJoin
which will call an array of observables and wait till the array of values is returned in subscription. First declarefeed
class variable as anObservable
.feed: Observable<any>;
Then in your
loadFeed():Observable<any[]>
return this.feed.switchMap((snapshots) => { let observableArray = []; snapshots.forEach(snapshot =>{ observableArray.push(this.pullFeedData(snapshot.val())); }); return Observable.forkJoin(observableArray) })
这篇关于离子3 - 更新与异步数据可观察的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!