Class: PurePromise

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/pure_promise/coercer.rb,
lib/pure_promise.rb,
lib/pure_promise/callback.rb

Overview

This coerces a thenable into a PurePromise I wanted to keep this separate because there are a lot of edge cases that need handling if the thenable doesn’t conform to the spec properly.

Defined Under Namespace

Classes: Callback, Coercer

Constant Summary collapse

MutationError =
Class.new(RuntimeError)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|method(:fulfill), method(:reject)| ... } ⇒ PurePromise

Returns a new instance of PurePromise.

Yields:

  • (method(:fulfill), method(:reject))


26
27
28
29
30
31
# File 'lib/pure_promise.rb', line 26

def initialize
  @state = :pending # Pending/fulfilled/rejected
  @callbacks = []

  yield method(:fulfill), method(:reject) if block_given?
end

Class Method Details

.error(message_or_exception = nil, message = nil, backtrace = nil) ⇒ Object

TODO: Clean this up, it’s pretty messy.



14
15
16
17
18
19
20
21
22
23
# File 'lib/pure_promise.rb', line 14

def error(message_or_exception=nil, message=nil, backtrace=nil)
  backtrace ||= caller(2) # Fix for jRuby - See https://github.com/jruby/jruby/issues/1908
  if message_or_exception.respond_to?(:exception)
    exception = message_or_exception.exception(message || message_or_exception)
  else
    exception = RuntimeError.new(message_or_exception)
  end
  exception.set_backtrace(backtrace)
  reject(exception)
end

Instance Method Details

#catch(&block) ⇒ Object



44
45
46
# File 'lib/pure_promise.rb', line 44

def catch(&block)
  self.then(null_callback, block || null_callback)
end

#fulfill(value = nil) ⇒ Object



48
49
50
# File 'lib/pure_promise.rb', line 48

def fulfill(value=nil)
  mutate_state(:fulfilled, value, @callbacks.map(&:first))
end

#reject(value = nil) ⇒ Object



52
53
54
# File 'lib/pure_promise.rb', line 52

def reject(value=nil)
  mutate_state(:rejected, value, @callbacks.map(&:last))
end

#resolve(promise) ⇒ Object

TODO: Rename method to: receive? acquire? take?



60
61
62
63
64
65
66
67
68
69
# File 'lib/pure_promise.rb', line 60

def resolve(promise)
  if equal?(promise)
    raise TypeError, 'Promise cannot be resolved to itself'
  elsif Coercer.is_thenable?(promise)
    Coercer.coerce(promise, self.class).resolve_into(self)
    self
  else
    raise TypeError, 'Argument is not a promise'
  end
end

#resolve_into(pure_promise) ⇒ Object

Raises:

  • (TypeError)


71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/pure_promise.rb', line 71

def resolve_into(pure_promise)
  raise TypeError, 'Argument must be of same type as self' unless pure_promise.instance_of?(self.class)

  if fulfilled?
    pure_promise.fulfill(@value)
  elsif rejected?
    pure_promise.reject(@value)
  else
    self.then(pure_promise.method(:fulfill), pure_promise.method(:reject))
  end
  self
end

#then(fulfill_callback = null_callback, reject_callback = null_callback, &block) ⇒ Object

REVIEW: Consider having two callback chains, to avoid having potentially expensive null_callbacks littering @callbacks



34
35
36
37
38
39
40
41
42
# File 'lib/pure_promise.rb', line 34

def then(fulfill_callback=null_callback, reject_callback=null_callback, &block)
  fulfill_callback = block if block
  self.class.new.tap do |return_promise|
    register_callbacks(
        Callback.new(fulfill_callback, return_promise),
        Callback.new(reject_callback, return_promise)
    )
  end
end