Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data flickers when promise changes #15

Open
taras opened this issue Sep 19, 2016 · 18 comments
Open

Data flickers when promise changes #15

taras opened this issue Sep 19, 2016 · 18 comments

Comments

@taras
Copy link

taras commented Sep 19, 2016

If you consider this scenario,

{{#each (await promise) as |item|}}
  {{item}}
{{/each}}

When the promise changes, the result of (await promise) changes to null while the promise is unfulfilled. This causes the list to be torn down while promise is resolving. Instead, it should continue to show the last value until the promise is resolved.

Thoughts?

@fivetanley
Copy link
Owner

I think this would be a confusing thing in the error scenario. If you want to avoid flickering you could always use is-pending/etc to show a loading indicator.

@fivetanley
Copy link
Owner

But maybe this could work out, I'm not sure of the implications yet.

@taras
Copy link
Author

taras commented Oct 10, 2016

@fivetanley I found a better way to do this with ember-concurrency. task.lastSuccessful.value gives a steady value while promise is inflight.

@taras taras closed this as completed Oct 10, 2016
@fivetanley
Copy link
Owner

Awesome, I wish we could depend on ember concurrency

@taras
Copy link
Author

taras commented Oct 10, 2016

Why can't we?

@fivetanley
Copy link
Owner

Don't want to bring in the large runtime dependency

@taras
Copy link
Author

taras commented Oct 10, 2016

Right...

@fivetanley
Copy link
Owner

When more browsers support generators out of the box, I definitely would love to reconsider, but regenerator/babel can be huge... Maybe we can change the implementation here to have this behavior after thinking about it for a bit.

@fivetanley
Copy link
Owner

fivetanley commented Oct 10, 2016

Might be as simple as Ember.run.scheduleOnce(this, this.recompute) here https://github.com/fivetanley/ember-promise-helpers/blob/master/addon/helpers/await.js#L70

@fivetanley fivetanley reopened this Oct 10, 2016
@taras
Copy link
Author

taras commented Oct 10, 2016

scheduleOnce on which event?

@fivetanley
Copy link
Owner

on recompute, to only call it once

@taras
Copy link
Author

taras commented Oct 10, 2016

Hmm... ok, not sure how that'll look :)

@jrjohnson
Copy link
Contributor

I too would like to see this working without needing to introduce a task into the mix. Right now I have to schedule ember-concurrency tasks to run in didRecieveAttrs just to avoid this flicker when passed values trigger computed property changes in a promise based list. Would be awesome if this didn't happen. I tried making the quick edit that @fivetanley suggested in await.js, but I get errors and I don't know enough about the runLoop to compensate for them.

Adding a loading indicator is sort of a solution but then it just flickers to the loader and then back to the list.

@magistrula
Copy link

Let's say we have a model foo that defines the following relationship:

// app/models/foo.js
bar: DS.belongsTo('bar')

I tried logging the following in a template:

{{log foo.bar.isPending (is-pending foo.bar)}}

When I refreshed the page, both logged as true then as false once bar resolved (as expected). Then, I interacted with a page in a way that updated and saved foo. The logs showed that foo.bar.isPending remained false, but (is-pending foo.bar) flipped to true then right back to false. This caused a flicker in the UI, because I have an {{#if}} block that depends on (is-pending foo.bar).

(is-pending foo.bar) recomputes when foo is saved, and I'm seeing that this condition evaluates to false when the new bar promise is compared to the old bar promise. this._wasSettled is true, but promise === this._promise is false. Both promises refer to the same bar model though, because promise.content === this._promise.content. Incidentally, promise.isFulfilled is true.

@fivetanley, Would it be appropriate for that condition to compare promise.content and this._promise.content in the case where promise and this._promise are DS promises?

@fivetanley
Copy link
Owner

@magistrula do you have a video demonstration of the bug? That solution sounds on the right track to me but I'd like to understand the bug a bit better.

@magistrula
Copy link

@fivetanley, I set up this twiddle reproducing the issue. If you have the console open, you'll see the log statements I was referring to. I also included logs in the {{#if}} and {{else}} blocks to demonstrate that those sections re-render (which means any components in that section would be destroyed, re-inserted, and go through their whole life cycle again). Interestingly, I found that the issue only occurs is bar is re-set on foo before foo is saved (see controllers/application).

@DavidPhilip
Copy link

This still is kind of a bummer. Anything I can do to help here?

@fivetanley
Copy link
Owner

@DavidPhilip if you want to take a stab at a bugfix PR + test that would be really helpful, I haven't noticed this in our apps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants