More efficient message passing in both directions

- Server batches up all output changes and sends them at the end
- Client only sends input update messages if the value actually changed
This commit is contained in:
Joe Cheng
2012-06-21 20:49:20 -07:00
parent 51e66f8aee
commit d5c49a80f9
2 changed files with 40 additions and 25 deletions

View File

@@ -85,23 +85,30 @@ def run_shiny_app(shinyapp)
shinyapp.websocket = ws
ws.onclose { exit(0) }
ws.onmessage do |msg|
puts "RECV: #{msg}"
begin
puts "RECV: #{msg}"
msg_obj = JSON.parse(msg)
case msg_obj['method']
when 'init'
msg_obj['data'].each do |k, v|
shinyapp.session.set(k, v)
msg_obj = JSON.parse(msg)
case msg_obj['method']
when 'init'
msg_obj['data'].each do |k, v|
shinyapp.session.set(k, v)
end
React::Context.flush
shinyapp.instantiate_outputs
when 'update'
msg_obj['data'].each do |k, v|
shinyapp.session.set(k, v)
end
end
React::Context.flush
shinyapp.instantiate_outputs
when 'update'
msg_obj['data'].each do |k, v|
shinyapp.session.set(k, v)
end
shinyapp.flush_output
rescue Exception => e
puts "ERROR: #{e}"
puts e.backtrace.collect {|x| "\t#{x}"}
raise
end
React::Context.flush
end
end
end
@@ -113,6 +120,7 @@ class ShinyApp
def initialize
@session = React::Session.new
@outputs = {}
@invalidated_output_values = Hash.new
end
def websocket=(value)
@@ -128,16 +136,21 @@ class ShinyApp
proc = @outputs.delete(name)
React::Observer.new do
value = proc.call
msg = {}
msg[name] = value
puts "SEND: #{JSON.generate(msg)}"
@websocket.send(JSON.generate(msg))
@invalidated_output_values[name] = value
end
end
end
def flush_output
return if @invalidated_output_values.empty?
data = @invalidated_output_values
@invalidated_output_values = Hash.new
puts "SEND: #{JSON.generate(data)}"
@websocket.send(JSON.generate(data))
end
def run
run_shiny_app self
end
end

View File

@@ -124,13 +124,15 @@
// TODO: If submit button is present, don't send anything
// until submit button is pressed
initialValues[name] = value;
var onChange = function() {
var data = {};
data[name] = elementToValue(input);
shinyapp.sendInput(data);
};
$(input).keyup(onChange);
$(input).change(onChange);
$(input).bind('change keyup input', function() {
var newValue = elementToValue(input);
if (value !== newValue) {
value = newValue;
var data = {};
data[name] = value;
shinyapp.sendInput(data);
}
});
});
shinyapp.connect(initialValues);