Skip to content

Instantly share code, notes, and snippets.

@judofyr
Created September 4, 2011 11:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save judofyr/1192720 to your computer and use it in GitHub Desktop.
Save judofyr/1192720 to your computer and use it in GitHub Desktop.
require 'camping'
Camping.goes :Async
module Async
def service(*a)
return super unless respond_to?(:async?)
EM.next_tick do
send(@method, *a)
end
throw :async
end
end
module Async::Helpers
class DeferrableBody
include EventMachine::Deferrable
def call(body)
body.each do |chunk|
@body_callback.call(chunk)
end
end
def each &blk
@body_callback = blk
end
end
ASYNC_CALLBACK = 'async.callback'.freeze
def stream
@body = []
@stream ||= DeferrableBody.new
res = to_a
res[2] = @stream
@env[ASYNC_CALLBACK].call(res)
end
def push(body)
body = Array(body) unless body.respond_to?(:each)
@async.call(body)
end
def finish(str = "")
if @stream
@async.succeed
else
@body ||= str
@env[ASYNC_CALLBACK].call(to_a)
end
end
end
module Async::Controllers
def self.A(*r)
R(*r).class_eval do
def async?; true end
self
end
end
# Inherit from A to create async response
class Index < A '/'
def get
EM.add_timer(2) do
# Call #finish to render stuff
finish render(:index)
end
end
end
class Push < A '/push'
def get
# Call #stream to start a streaming response
stream
EM.add_timer(1) do
# Push stuff out
push "Hello\n"
end
EM.add_timer(2) do
# Push more stuff
push render(:index)
# Call #finish to close
finish
end
end
end
end
module Async::Views
def index
p 'Hello'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment