lib/em-promise/defer.rb in em-promise-1.0.1 vs lib/em-promise/defer.rb in em-promise-1.0.2

- old
+ new

@@ -22,24 +22,20 @@ wrappedCallback = proc { |value| begin result.resolve(callback.nil? ? value : callback.call(value)) rescue => e - # - # TODO:: add debugging output here - # + warn "\nUnhandled exception: #{e.message}\n#{e.backtrace.join("\n")}\n" result.reject(e); end } wrappedErrback = proc { |reason| begin result.resolve(errback.nil? ? Defer.reject(reason) : errback.call(reason)) rescue => e - # - # TODO:: add debugging output here - # + warn "Unhandled exception: #{e.message}\n#{e.backtrace.join("\n")}\n" result.reject(e); end } # @@ -73,10 +69,11 @@ end class ResolvedPromise < Promise def initialize(response, error = false) + raise ArgumentError if error && response.is_a?(Promise) @error = error @response = response end def then(callback = nil, errback = nil, &blk) @@ -109,15 +106,13 @@ callbacks = @pending @pending = nil @value = ref(val) if callbacks.length > 0 - EM.next_tick { - callbacks.each do |callback| - @value.then(callback[0], callback[1]) - end - } + callbacks.each do |callback| + @value.then(callback[0], callback[1]) + end end end end end @@ -166,16 +161,57 @@ # @param [Object] reason constant, message, exception or an object representing the rejection reason. def self.reject(reason = nil) return ResolvedPromise.new( reason, true ) # A resolved failed promise end + # + # Combines multiple promises into a single promise that is resolved when all of the input + # promises are resolved. + # + # @param [Promise] a number of promises that will be combined into a single promise + # @returns [Promise] Returns a single promise that will be resolved with an array of values, + # each value corresponding to the promise at the same index in the `promises` array. If any of + # the promises is resolved with a rejection, this resulting promise will be resolved with the + # same rejection. + def self.all(*promises) + deferred = Defer.new + counter = promises.length + results = [] + + if counter > 0 + promises.each_index do |index| + ref(promises[index]).then(proc {|result| + if results[index].nil? + results[index] = result + counter -= 1 + deferred.resolve(results) if counter <= 0 + end + result + }, proc {|reason| + if results[index].nil? + deferred.reject(reason) + end + reason + }) + end + else + deferred.resolve(results) + end + + return deferred.promise + end + protected - def ref(value) + def self.ref(value) return value if value.is_a?(Promise) return ResolvedPromise.new( value ) # A resolved success promise + end + + def ref(value) + Defer.ref(value) end end end