grych / drab

Remote controlled frontend framework for Phoenix.
https://tg.pl/drab
MIT License
877 stars 43 forks source link

Optimistic updates #64

Open grych opened 7 years ago

grych commented 7 years ago

In analogy to execjs, we could integrate ElixirScript into Drab and write the whole stuff in Elixir only.

exec socket do
    Todo.Data.Http.fetch("/api/todo").then(fn(response) ->
      response.json()
    end).then(fn(todos) ->
        todos
      |> Enum.map(fn(x) -> %Todo.Todo{ id: x.id, completed: x.completed, title: x.title } end)
      |> Todo.Main.update()
    end).catch(fn(err) ->
      Todo.Data.Http.log(err)
    end)
end
grych commented 6 years ago

It also can help solve the issue with optimistic updates.

optimistic_before :save_data do
  set_prop "#name", value: "...processing...", disabled: true
end

def save_data(socket, _sender) do
  set_prop socket, "#name", value: Database.get_name()
end

optimistic_after :save_data do
  set_prop "#name", disabled: false
end

The code in optimistic_before and optimistic_after could be an ElixirScript.

x4lldux commented 6 years ago

Could you explain what "optimistic update" is? I'm not sure what do you mean by that and what it has to do with ElixirScript and I have a feeling that there are two different features here.

Also, adding ElixirScript could create a big source of confusion when interacting between a regular Elixir and ElixirScript:

defmodule TodoCommander do
  use Drab.Commander
  ...
  def add_new_item(socket, title) do
    new_item = %Todo.Todo{title: tile, completed: false, id: UUID.new()}
    exec socket do
       Todo.List.add_todo(new_item)
    end
  end
end

This would not work, because new_item is created outside of ElixirScript scope.

And all of that assuming the compilation problem of those exec blocks would be solved. As far as I've checked ElixirScripts code, it traverse an entry module to find all the dependency functions, structs, and modules. The Todo.Todo struct is something that needs not be already known during compilation of this snippet but the resulting JS code should not contain the Todo.Todo module or any other module; just the JS equivalent of Todo.List.add_todo call - which would probably look like this:

var _result = Todo.List.add_todo(var0)

So the Drab<->ElixirScript combo would need to somehow know, which modules compiled to JS were already loaded by the browser.

grych commented 6 years ago

Optimistic update is an action done on the client side, before the server respond, to make a latency compensation which makes the user experience better. See the discussion started here https://elixirforum.com/t/drab-phoenix-library-for-server-side-dom-access/3277/283?u=grych

Optimistic updates are not in the scope of 1.0 anymore, I'll leave it for a future. As now, I am thinking about just providing an API to put JS as a string. We will see.

About ElixirScript, this is a rather an idea and a discussion, than the real implementation plan. And it is not even possible yet.

This would not work, because new_item is created outside of ElixirScript scope.

If the ES would be implemented, it must be solved somehow.