Loop through Observable data, push to array, and d

2019-02-26 03:07发布

问题:

How do i loop through my data, that i subscribed to as an Observable, push it to an array, and displaying the whole data of the array? My present code only displays data from each "page", and not all the pages. The reason why i want to do this, is because i want to make an infinity scroll.

Thank you!

Component:

  this.storiesService.getData(this.page, this.hits, this.feed)
  .subscribe(
  (data) => {
    console.log(data);
    if (!data || data.hits === 0) {
      this.finished = true;
      console.log("NO MORE HITS")
    } else {
      this.finished = false;
      for (let story of data.hits) {
        this.hitsArray.push(story);
        console.log("Hit me!")
        console.log(this.hitsArray);
      }
    }
  })

HTML:

 <div class="col-4 col-md-4 col-sm-12" *ngFor="let story of hitsArray">
  <div class="thumbnail">
    <img *ngIf="story.storyMediaType === 'image'" class="img-fluid" src="{{story.storyThumbnailImage}}" />
    <img *ngIf="story.storyMediaType === 'video'" class="img-fluid" src="{{story.storyThumbnailImage}}" width="150" height="94" />
    <div class="caption">
      <p>{{story.storyCity}}, {{story.storyCountry}}</p>
      <h3>{{story.storyHeadline}}</h3>
      <p>Uploadet {{story.uploadDate}}</p>
      <p>Bruger: {{story.userDisplayName}}</p>
      <p><a href="#" class="btn btn-primary" role="button">Like</a> <a href="#" class="btn btn-default" role="button">Button</a></p>
    </div>
  </div>
</div>

回答1:

Based on your component's template, you are using data which is updated for every newly fetched data from observable here in your subscription

for (let story in data) {
        this.data = data; --> here you update regularly

from the above you are saying for every array key update our this.data which seems wrong, because the keys in an array is 0,1,2 which are the index.

Both for..of and for..in statements iterate over lists; the values iterated on are different though, for..in returns a list of keys on the object being iterated, whereas for..of returns a list of values of the numeric properties of the object being iterated. readmore

So instead of the long trip your subscription code that handles the processing of the retrieved data should look like the one below

for (let story of data) { // now of
       // this.data = data; not needed else your data is always overriden
       // for (let i = 0; i < this.data.length; i++) { no need for this again since the above for..of is handling it
          this.hitsArray.push(story);
          this.data.hits.push(story);// add the new stories(as last element) to the main data array using this.data here now

          console.log(this.hitsArray);
      //  } for loop of this.data.length
      }

So with the above code following the comments should explain what the code is doing and how the irrelevant parts are causing data override.

P.S. your this.data.hits must be an array initialized as [] when the program is loading the component. And your data from your observable must be an array or if object with hits as array then use this code instead for (let story in data.hits) {.

Hope this helps.



回答2:

So this is the final fix (note: the hitsArray is being loaded as an empty array, every time the params changes):

Component:

this.storiesService.getData(this.page, this.hits, this.feed)
  .subscribe(
  (data) => {
    console.log(data);
    if (!data || data.hits == 0) {
      this.finished = true;
      console.log("No more hits :-(")
    } else {
      this.finished = false;
      for (let story of data.hits) {
        this.hitsArray.push(story);
        console.log("Hit me!")
        console.log(this.hitsArray);
      }
    }
  })

HTML:

 <div class="col-4 col-md-4 col-sm-12" *ngFor="let story of hitsArray">
  <div class="thumbnail">
    <img *ngIf="story.storyMediaType === 'image'" class="img-fluid" src="{{story.storyThumbnailImage}}" />
    <img *ngIf="story.storyMediaType === 'video'" class="img-fluid" src="{{story.storyThumbnailImage}}" width="150" height="94" />
    <div class="caption">
      <p>{{story.storyCity}}, {{story.storyCountry}}</p>
      <h3>{{story.storyHeadline}}</h3>
      <p>Uploadet {{story.uploadDate}}</p>
      <p>Bruger: {{story.userDisplayName}}</p>
      <p><a href="#" class="btn btn-primary" role="button">Like</a> <a href="#" class="btn btn-default" role="button">Button</a></p>
    </div>
  </div>
</div>

Many thanks to @Theophilus for the suggestion! His example may work in most situations other than mine!