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

Alternative request/redraw integration #1444

Closed

Conversation

barneycarroll
Copy link
Member

This is a proposal relating to #1442. It allows redraw: false to be passed as an option to m.request when using bundled Mithril in a way that addresses @lhorie's concern that this would on the face of it be too tight a coupling between the request API to the render API - this does it in such a way that request is actually more generic, and isolates the request/redraw hooks to the bundling module.

It's difficult to write tests for this feature - I'm stymied by the fact that AFAICT I'd need to invoke both the piecemeal xhr & mock modules to test the bundled module - and I'm not sure how to do that.

Having said that, there were no tests for request/redraw integration in the first place, and this does pass all existing tests.

@tivac
Copy link
Contributor

tivac commented Dec 2, 2016

This doesn't look like the behavior quite matches what it's replacing.

Currently m.request wraps the Promise being returned so that the .then() function will always be wrapped and able to invoke whatever the completion callback is after the entire promise chain completes.

Your version looks like it'll call m.redraw() as soon as the request finishes, before any other .then() are run.

@barneycarroll
Copy link
Member Author

My understanding is that that isn't an issue, since the redrawService is subscribed to in m.mount, which always defers the actual recomputation by some value of time.

Sequential Promises chaining off the request will therefore always resolve before the actual view recomputation. Right?

@tivac
Copy link
Contributor

tivac commented Dec 2, 2016

So after a bunch of discussion in gitter (starting about here) I think we ended up in agreement.

  • The automatic redraw should happen at the end of the entire Promise chain
  • Other redraws invoked from code should not be blocked during the wait for the resolution of the Promise chain. The current implementation does this and it's not desired.

@barneycarroll @lhorie

@barneycarroll
Copy link
Member Author

@tivac yep, AFAIC this patch fulfills these criteria.

@leeoniya
Copy link
Contributor

leeoniya commented Dec 2, 2016

out of curiosity how do you guys determine the end of a promise chain? if m.request returns a promise how can it know when the chain is "done" presumably to chain a redraw to it?

@tivac
Copy link
Contributor

tivac commented Dec 2, 2016

@leeoniya The previous implementation wrapped the .then() method returned by the Promise.

@leeoniya
Copy link
Contributor

leeoniya commented Dec 2, 2016

thanks, i suspected it wasn't a bare es6 promise. i understand how you can auto-chain the redraw. but still not how you can determine that the chaining is completed without an explicit external .end() call or similar. it seems like something stream.end() subscribers can do though...

@lhorie
Copy link
Member

lhorie commented Dec 2, 2016

@barneycarroll this PR doesn't work; it redraws too early (run npm run dev and try ThreadItJS example in your folder)

@lhorie lhorie closed this Dec 2, 2016
@barneycarroll
Copy link
Member Author

This raises a lot of awkward issues :/

@leeoniya is right, this relies on a decorated promise implementation and assigns dubious semantics to it. A promise can be forked, chained, passed to other contexts. A receiving context from one of these forks may well sit on that promise reference until an arbitrary condition resolves and only then declare a dependency upon it. The idea that Mithril can determine when the chain ends is fallacious.

The magic interpretation of intent involved here is too high: either a request should always trigger a redraw on resolution, or never. Anything in between is too difficult to reason about, and therefore not a viable convenience feature.

I think the desired intent of this patch is good - ie, you will get an async redraw as a result of requests and event handlers settling. Advanced users can opt out, after all - in component code or by building their own non-auto Mithril (at their own peril). What do we reckon?

@dead-claudia
Copy link
Member

dead-claudia commented Dec 3, 2016

@barneycarroll This is why I don't want m.request to have any redraw semantics whatsoever. It's too magical to reliably implement, even with a custom static compiler.

There's always promise.then(m.redraw), which is maybe one extra line tops.

@lhorie
Copy link
Member

lhorie commented Dec 3, 2016

it works like this now: https://github.com/lhorie/mithril.js/blob/rewrite/request/tests/test-request.js#L301-L317

Standalone has no redraw semantics

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

Successfully merging this pull request may close these issues.

5 participants