Ionic 3 super slow with firebase on device/emulator

It’s empty, doesn’t carry my user object… Nothing is being displayed

How are you defining src in your template?

@AaronSterling i’m defining it like that

<img class="user" [src] ="(user | async).img"/>

You’re doing something wrong. 100% guarantee. What I gave you is from the AngularFire documentation. You aren’t posting enough code for us to see where you are making your mistake. If the original slowness is happening because of the reason I think it’s happening, the code I gave you will fix it immediately.

Edited to add: if your class user treats user as something other than an Observable, that’s the issue right there.

@AaronSterling I have uploaded the whole code to github, its a very simple code…
Please try to run it on simulator/real device using ionic3 and same dependencies in package.json.

It’s not showing up because you use user in ngIf. You neglected to include this in your posts here. Maybe other problems too.

But look. You’re letting Angular check changes to user whenever it wants, by your user? syntax, and then you are changing user inside an asynchronous call. So the change detection is only guaranteed to happen eventually, not right away. If instead you push the subscription to the async pipe (as the AF2 documentation recommends) then it is Angular’s job to make a change right away once the AF observable emits. So if you want faster response across multiple devices, follow the AF documentation. If you based your code off of some example you saw online, well, that code example probably wasn’t very high quality.

Did you run/read the code carefully before accusing me of neglecting? the ng*If is only to show the spinner at the time of sending request to firebase server, which is working correctly. This has nothing to do with preventing data from showing up.
Simply when the user object has a value it displays it, other wise it do not. There is no mistake with that part and you can try it yourself.
Setting user to this.angularfire.database.object('/accounts/' + this.uid); makes the condition true. So the div was showing but the value was not coming.
Please try it by yourself in the same versions I have in my dependencies and let me know.
Please also bear in mind that this was working fine before I have upgraded to ionic3.

<div *ngIf="user">
    <ion-row >
      <ion-col width-20> 
  <img class="user" src ="{{user?.img}}"/>
  </ion-col >
  <ion-col width-67 class="name">
    <p>{{user?.name}}</p>
  </ion-col>
  <ion-col width-10>
  </ion-col>
  </ion-row>
</div>
  <ion-item  class="welcome" (click)="editProfile()">
    <div *ngIf="user">
    <ion-row >
      <ion-col width-20> 
  <img class="user" src ="{{user?.img}}"/>
  </ion-col >
  <ion-col width-67 class="name">
    <p>{{user?.name}}</p>
  </ion-col>
  <ion-col width-10>
  </ion-col>
  </ion-row>
    </div>
    <ion-spinner name="circles" *ngIf="!user"></ion-spinner>
  </ion-item>

Please read it all as you missed the spinner part… Anyways i’m quite sure there’s no error with that part. If you have doubts, please try it yourself.

You reported an error, in this exact code, in your OP. I’m telling you how to fix the error. You fix the error by following the AngularFire documentation. I don’t know why you’re trying to argue with me, unless you already tried the documentation, it didn’t work, and so you did this instead. I don’t understand what you have to lose by following the documentation.

You are assuming I didn’t try it. However, I did from the first time you asked me. And as I have said it is not getting my object from the database, it simply can not find it if i use this method you suggested me to use. And yes without the if condition it results in an error in this method. Whereas, using the method I had results in finding it but it takes time.

Did you change your ngIfs to *ngIf=“user | async” ?

Don’t be offended when asking for help and getting it :slight_smile: . Sometimes when we write something down it might sound judgmental, but believe me when I’m saying @AaronSterling is just trying to help you out.

When it comes down to the topic; the devil is in the details. Sometimes the small things make everything come crashing down. Bare with us, try the possible solutions as proposed.

I have used the code in the way you suggested and I have also made a video of my experience with it. It ended up giving the same result I had with the other method, please have a look and tell me if you have concerns.

<ion-content  padding>
  
   <ion-item  class="welcome" (click)="editProfile()">
    <div *ngIf="user | async">
    <ion-row >
      <ion-col width-20> 
  <img class="user" [src] ="(user | async).img"/>
  </ion-col >
  <ion-col width-67 class="name">
  <p> Welcome, {{(user | async).name}} </p>
  </ion-col>
  <ion-col width-10>
  </ion-col>
  </ion-row>
    </div>

   <ion-spinner name="circles" *ngIf="!(user | async)"></ion-spinner> 
  </ion-item>  
ionViewDidLoad() {
   // console.log('ionViewDidLoad WelcomePage');
    this.user = this.angularfire.database.object('/voda/' + this.uid);
}

Can you elaborate a bit here? I’m not seeing a fundamental difference between:

A:

<div>{{(user | async).name}}</div>
user = af.database.object();

B:

<div>{{user.name}}</div>
user = {}
af.database.object().subscribe(user => this.user = user);

Yes, the AsyncPipe does nifty things like managing unsubscriptions for you, but I can’t think of why there would be any performance difference between using it and doing the subscription manually.

Those seem the same to me. But the OP is also using user?, which I believe makes a difference.

Ofcourse I’m not, I really do appreciate every help and any kind of support. I have no doubts @AaronSterling is doing his best to help me, and I’m very thankful and grateful to those efforts :slight_smile:

I’m not a huge fan of the Elvis operator, because I think the responsibility for making all template-accessed properties be in a sane state is the controller’s responsibility, and the template shouldn’t have to be defensive about it.

That being said, I can’t conceive of it having any measurable performance impact. It just gets inlined as isValueBlank(user) ? null : user.name, and wouldn’t get reevaluated until user changes, which would happen when the AF observable emits.

Can you describe in a bit more detail what changes you made to the app code and its dependencies between when you liked the performance and now? Were you using Angular 2 before and now are using Angular 4? Are you using the lazy page loading code splitting system now and weren’t before? Are all your pages and components in a single module? Any other significant version bumps in potentially relevant dependencies?

I believe it has an effect because the reported problem doesn’t exist in the browser but does exist in devices, where change detection is more expensive. (Or costs the same, but fewer resources.) So if Angular ticks, sees a null, then waits a while to tick again, it isn’t the same. One way to test whether slow change detection is the issue here would be to force detectChanges() inside the subscription as soon as the user is read from Firebase. It seems really unlikely that Firebase is slow, because I’ve done a lot of different types of AF calls, in multiple environments, and it’s always been responsive.

As I understand it, change detection doesn’t just sit around periodically polling things. All the asynchronous stuff like setTimeout() (which RxJS relies upon internally) is patched to trigger change detection when it resolves. So it should fire as soon as a new user comes from the AF Observable.

That’s an interesting experiment. In this situation, I would be pretty surprised if it had a noticeable effect.