Skip to content

Instantly share code, notes, and snippets.

@vitaly
Created January 10, 2012 22:55
Show Gist options
  • Save vitaly/1591720 to your computer and use it in GitHub Desktop.
Save vitaly/1591720 to your computer and use it in GitHub Desktop.
# Lets say you have f1, f2, f3 - functions provided by some API that you can't change
# and they use the standard (err, res...) callback scheme
# then suppose you need to call 3 of them one after the other
# the usual js way will be this:
foo = (params, callback) ->
f1 something, (err, res) ->
if err
callback err
else
f2 something, (err, res) ->
if err
callback err
else
f3 something, (err, res) ->
if err
callback err
else
callback err, something(res)
# and this is how we call this func
foo params, (err, res) ->
if err
do_error err
else
do_ok res
## first lets try to refactor the error handling
error_handler = (errcallback, callback) ->
(err, res...) ->
if err
errcallback err
else
callback res...
foo = (params, callback) ->
f1 something, error_handler callback, (res) ->
f2 something, error_handler callback, (res) ->
f3 something, error_handler callback, (res) ->
callback null, something(res)
# MUCH better ;)
#usage still the same
foo params, (err, res) ->
if err
do_error err
else
do_ok res
## now lets try to rewrite with emiter
with_emiter = (em, callback) ->
(err, res...) ->
if err
em.emit "error", err
else
callback res...
foo = (params, callback) ->
em = new EventEmitter
f1 something, with_emiter em, (res) ->
f2 something, with_emiter em, (res) ->
f3 something, with_emiter em, (res) ->
callback res
em
foo params, (res) ->
do_ok res
.on "error", (err) ->
do_error err
# with jQuery Deferred
deferred = (d, callback) ->
(err, res...) ->
if err
d.reject err
else
callback res...
# if we can't have all the callbacks sharing context with 'd' we will have to pass it around
# like callback d, res... in deferred and having deferred d, (d, res) -> in foo
foo = (params, d = $.Deferred()) ->
f1 something, deferred d, (res) ->
f2 something, deferred d, (res) ->
f3 something, deferred d, (res) ->
d.resolve res
d
d = foo
d.done (res) ->
do_ok res
d.error (err) ->
do_error err
# enother try, this time lets try to use deferrads for success too
deferr = (func, args...) ->
d = $.Deferred()
func args..., (err, res...) ->
if err
d.reject err
else
d.resolve res...
d
foo = (params) ->
d = $.Deferred()
d1 = deferr f1, something
d1.fail (err) ->
d.reject(err)
d.done (res) ->
d2 = deferr f2, something
d2.fail (err) -> d1.reject err
f2.done (res) ->
d3 = deferr f3, something
d3.fail (err) -> d2.reject err
d3.done (res) ->
d.resolve res
d
# AGAIN
deferr = (d, func, args...) ->
d2 = $.Deferred()
func args..., (err, res...) ->
if err
d.reject err
else
d2.resolve res...
d2
foo = (params) ->
d = $.Deferred()
deferr(d, f1, something).done (res) ->
deferr(d, f2, something).done (res) ->
deferr(d, f3, something).done (res) ->
d.resolve(res)
# another
deferred = (errd) ->
d = $.Deferred()
callback = (err, res...) ->
if err
errd.reject err
else
d.resolve res...
callback.done = _.bind(d.done, d)
callback
foo = (params) ->
d = $.Deferred
f1 something, deferred(d).done (res) ->
f2 something, deferred(d).done (res) ->
f3 something, deferred(d).done (res) ->
d.resolve res
d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment