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

Changes in subscriptions without effect if model changes in response to command from init #1776

Open
JaSpa opened this Issue Aug 31, 2018 · 8 comments

Comments

Projects
None yet
8 participants
@JaSpa
Copy link

JaSpa commented Aug 31, 2018

This is a problem with elm 0.19.0.

SSCCE

import Browser
import Html exposing (Html)
import Task
import Time exposing (Posix, Zone)

type Model
    = Loading
    | HasZone Zone

type Msg
    = NewZone Zone
    | Tick Posix

main =
    Browser.element
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }

init : () -> ( Model, Cmd Msg )
init _ =
    ( Loading, Task.perform NewZone Time.here )

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case Debug.log "update in response to" msg of
        NewZone zone ->
            ( HasZone zone, Cmd.none )
        Tick _ ->
            ( model, Cmd.none )

subscriptions : Model -> Sub Msg
subscriptions model =
    case Debug.log "subscriptions for" model of
        Loading ->
            Sub.none
        HasZone _ ->
            Time.every 1000 Tick

view : Model -> Html Msg
view model =
    Debug.log "view for" model
        |> always (Html.text "Nothing to see here, please look at the console.")

Ellie by @adeschamps showing the same problem: https://ellie-app.com/38yPbFdvv6qa1

Expected behaviour

In the browser's console the messages from Debug.log should appear in this order:

  1. view for Loading
  2. subscriptions for Loading
  3. update in response to NewZone
  4. subscriptions for HasZone
  5. view for HasZone
  6. update for Tick
  7. subscriptions for Tick
  8. view for Tick

with the last three steps repeated every second.

Actual behaviour

In the browser's console the following messages appear:

  1. view for Loading
  2. subscriptions for Loading
  3. update in response to NewZone
  4. subscriptions for HasZone
  5. view for HasZone

Analysis

  • Core problem: older subscriptions overwrite newer subscriptions.
  • Happens if: the command returned from the init function alters the model in such a way that the subscriptions change.
  • Guess on the problem location: _Platform_dispatchEffects. In the for-in loop is no ordering between subscriptions and commands.

More detailed breakdown

Expected

  1. Call to init getting the first model
  2. Setting subscriptions based on the first model
  3. Executing the command returned from init
  4. Call to update getting a new model
  5. Setting subscriptions based on the new model
  6. Executing the returned command
  7. etc. …

Actual

  1. Call to init getting the first model
  2. Executing the command returned from init
  3. Call to update getting a new model
  4. Setting subscriptions based on the new model
  5. Setting subscriptions based on the first model

This bug was first reported in #1762 by @jatinderjit.

@JaSpa JaSpa changed the title Changes in subscription without effect if model changes in response to command from init Changes in subscriptions without effect if model changes in response to command from init Aug 31, 2018

@Bastes

This comment has been minimized.

Copy link

Bastes commented Oct 25, 2018

I have encountered that same issue. This is really problematic ; is there anything that can be done to work around it?

@Bastes

This comment has been minimized.

Copy link

Bastes commented Oct 25, 2018

Well, so far what I found is: never make conditional subscriptions. Not very satisfying and probably not optimal performance-wise, but eh.

@Carlsson87

This comment has been minimized.

Copy link

Carlsson87 commented Nov 6, 2018

I encountered the same problem and reported it here: elm/browser#49. I closed that issue since it is pretty much a duplicate of this one.

@caseyhoward

This comment has been minimized.

Copy link

caseyhoward commented Nov 14, 2018

I think I'm running into the same thing. I have an app modeled pretty similarly to the elm-spa-example. The elm-spa-example uses subscriptions with a model argument, however they all seem to be using the data off the model so maybe it's not an issue there. What I'm seeing is my subscribe function being called with the correct model and then the port the subscription is based off of getting called with an entirely wrong model from before. The model being passed in exists nowhere in the state tree at all when viewing with the elm-debugger.

@jhillyerd

This comment has been minimized.

Copy link

jhillyerd commented Nov 19, 2018

I also seem to be effected by this, my port was working fine in Elm 0.18, but now does send any messages unless it was subscribed during initial page load.

@ashishsc

This comment has been minimized.

Copy link

ashishsc commented Nov 26, 2018

Seen a few people run into this now. The biggest issue with not being able to conditionally subscribe is that in development mode, the elm debugger becomes impossible to use if you are say, subscribing to animation frames or time.

@ericnething

This comment has been minimized.

Copy link

ericnething commented Apr 6, 2019

I am having this same issue, but sometimes (~5-10% of the time) it randomly works. When I created a minimal example where the subscriptions are all initialized on page load (and no conditionals) it works as expected. This bug is a serious problem for any non-trivial application, like the one I am building here.

@bburdette

This comment has been minimized.

Copy link

bburdette commented Apr 8, 2019

For me its ok if I change my subscription flag { model | animate = True } in a Msg generated directly by the UI. But if I do the same in an event from a Cmd, no dice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.