Skip to content

Commit

Permalink
immediate: cleanup and add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
meh committed Jan 21, 2014
1 parent 677cad5 commit 634dbf9
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 11 deletions.
3 changes: 3 additions & 0 deletions opal/browser/compatibility/immediate.rb
Expand Up @@ -51,7 +51,10 @@ def prevent
`window.msClearImmediate(#@id)`
end
elsif C.post_message?
# @private
@@tasks = {}

# @private
@@prefix = "opal.browser.immediate.#{rand(1_000_000)}."

$window.on :message do |e|
Expand Down
42 changes: 38 additions & 4 deletions opal/browser/immediate.rb
@@ -1,26 +1,54 @@
require 'promise'

require 'browser/compatibility/immediate'

module Browser

# FIXME: drop the method_defined? checks when require order is fixed
# Class to easily create and dispatch an immediate call.
#
# Immediate calls are deferred function calls that happen as soon as they can
# be scheduled.
#
# Compatibility
# -------------
# The compatibility layer will try various implementations in the following
# order.
#
# + [setImmediate](https://developer.mozilla.org/en-US/docs/Web/API/Window.setImmediate)
# + [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage)
# + [readystatechange](https://developer.mozilla.org/en-US/docs/Web/Reference/Events/readystatechange)
# + [setTimeout](https://developer.mozilla.org/en/docs/Web/API/window.setTimeout)
#
# The order has been chosen from best to worst for both performance and
# preemptiveness.
#
# @todo drop the method_defined? checks when require order is fixed
class Immediate
# Create an immediate for the given function which will be called with the
# arguments and block.
#
# @param func [Proc] the function to call
# @param args [Array] the arguments to call it with
def initialize(func, args, &block)
@aborted = false
@function = func
@arguments = args
@block = block
end

# Dispatch the immediate.
#
# @abstract
def dispatch
raise NotImplementedError
end unless method_defined? :dispatch

# Prevent the immediate from being called once scheduled.
#
# @abstract
def prevent
raise NotImplementedError
end unless method_defined? :prevent

# Abort the immediate.
def abort
return if aborted?

Expand All @@ -30,6 +58,7 @@ def abort
self
end

# Check if the immediate has been aborted.
def aborted?
@aborted
end
Expand All @@ -38,13 +67,16 @@ def aborted?
end

class Proc
# Defer the function to be called as soon as possible.
# (see Immediate.new)
def defer(*args, &block)
Browser::Immediate.new(self, args, &block).tap(&:dispatch)
end
end

class Promise
# Create a promise which will be resolved with the result of the immediate.
#
# @param args [Array] the arguments the block will be called with
def self.defer(*args, &block)
new.tap {|promise|
proc {
Expand All @@ -57,3 +89,5 @@ def self.defer(*args, &block)
}
end
end

require 'browser/compatibility/immediate'
16 changes: 9 additions & 7 deletions spec/immediate_spec.rb
@@ -1,12 +1,14 @@
require 'spec_helper'
require 'browser/immediate'

describe Browser::Immediate do
async 'defers a proc' do
proc {|a|
run_async {
a.should == 42
}
}.defer(42)
describe Proc do
describe '#defer' do
async 'works properly' do
proc {|a|
run_async {
a.should == 42
}
}.defer(42)
end
end
end

0 comments on commit 634dbf9

Please sign in to comment.