~singpolyma/em_promise.rb

Defer through a Fiber trampoline

Instead of running all defer blocks on the EM reactor fiber, run in a dedicated
Fiber trampoline.  Inherit the trampoline from scope if present, or from the
promise you call #then on, or else make a new trampoline.  This means that all
callbacks on promises in a logical chain run in the same Fiber as each other,
but a different one from all other code, so Fiber-local variables are scoped to
the logical chain, like so:

    EMPromise.resolve(nil).then {
    	Thread.current[:fiber_local] = 123
    	promise_timer(1)
    }.then {
    	p Thread.current[:fiber_local] # 123
    }

This also allows us to mix promise-based and fiber-based code arbitrarily,
without any extra special helpers, including #sync itself, for example:

    EMPromise.resolve(nil).then {
		promise_timer(1).sync
		DB.exec("SQL")
    }
Support #sync on Defferable
eventmachine is a dependency
Allow users to catch only some errors

This implements the common pattern:

promise.catch do |e|
	if SomeError === e
		# handle
	else
		EMPromise.reject(e)
	end
end

It also allows for this usage for more granular catching:

promise.catch_only(filter: ->(e) { e == :done }) do
	"all done"
end