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

The semantics of render is very fragile #20

Open
dramforever opened this issue Aug 1, 2017 · 1 comment
Open

The semantics of render is very fragile #20

dramforever opened this issue Aug 1, 2017 · 1 comment

Comments

@dramforever
Copy link

dramforever commented Aug 1, 2017

Steps to reproduce

module Main where

import Transient.Base
import Transient.Move
import GHCJS.HPlay.View

import Data.Functor (void)
import Control.Concurrent (threadDelay)
import Control.Monad.IO.Class (liftIO)

main :: IO ()
main = void . keep . initNode . onBrowser . local $ do
  name <- render $ inputString Nothing `fire` OnKeyUp
  content <- liftIO $ do
    threadDelay 500000 -- simulate a delay
    pure ("Hello " ++ name)
  render $ rawHtml (p content)
  1. Build and run this
  2. Type 1234567890 at about 5 key strokes per second

Expected behavior

After it settles, I expect either

  1. 10 lines appearing, saying

    Hello 1
    Hello 12
    Hello 123
    ...
    

    and so on, one for each keyup event, or

  2. one line appearing, saying

    Hello 1234567890
    

    corresponding to the last keyup event

Actual Behavior

I only some of the corresponding lines.

If we think the action of getting content as a request, then the displayed results are the responses that arrived after the last event, whereas I expect either all or one response corresponding to the last to be displayed.

Observations

As I've shown in the example, this does not need to have atRemote to happen.

Replacing liftIO with async doesn't help

What does this have to do with render

I believe this behavior of render, is causing this:

If an event happens within the render parameter, it deletes the rendering of all subsequent ones.

But when the content has not arrived, the subsequent render is non-existent, so it is not affected by this. I believe this, although documented, is what's causing the strange behavior of the example program.

@agocorona
Copy link
Collaborator

At this moment multithreaded display in the browser is not solved well. inputString produces a new thread when an event happens. This is allowed since it could be useful for some purposes in order to make application responsive. There are some fixes:

  1. use threads 0 $ render . inputString...
  2. disabling the input box and enabling it after the rendering
  3. using at there is no duplication:
main = void . keep . initNode . onBrowser . local $ do
  name <- render $ inputString Nothing `fire` OnKeyUp <++ div ! id "result"
  content <- liftIO $ do
    threadDelay 500000 -- simulate a delay
    pure ("Hello " ++ name)
  render $ at "#result"  Insert $ rawHtml (p content)

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

2 participants