It would be interesting to see some code.
For example are you doing something like this:
update msg model =
case msg of
OnClick -> ({ model | busy = True, result = longCalc model }, Cmd.none)
Obviously in that case, the model with busy = True is not going to be produced until after the longCalc function completes.
Or are you doing like this:
message : msg -> Cmd msg
message x =
Task.perform identity (Task.succeed x)
update msg model =
case msg of
OnClick -> ({ model | busy = True }, message DoLongCalc)
DoLongCalc -> ({ model | result = longCalc model }, message Done)
Done -> ({ model | busy = False }, Cmd.none)
Which may fair better. At least it is returning control to the Elm runtime with busy = True, to update the view. However, the long running calculation can still block the UI thread and prevent the UI from being updated.
Elm renders the view during a Window.requestAnimationFrame(). So if the busy = True does not get picked up by the next animation frame, and the long running calculation is already started, I think the UI will get frozen out until the calculation completes.
The way I worked around this, is to split my calculation down into steps, and return a continuation for the next step at each step until the calculation is complete. Like this:
type CalcResult a =
Complete a
| Ongoing a (() -> Result a)
longCalc : Arg1 -> ... -> Argn -> SomeResultType -> CalcResult SomeResultType
So once you supply longCalc with its arg, you get a step function to go from the last intermediate result to the next one, which may be another intermediate result, or the final result of the calculation.
Then you can run a number of steps (maybe 100), in a single iteration of the update, then return control to Elm to render the UI, then calculate some more.
It works, but I found that generally doing too much calculation in the update loop will very negatively affect the responsiveness of the UI. It is also explicit application controller time-slicing which is not so nice to have to do - at least not in a high level language, you might expect to have to do stuff like that on a micro-controller or something.