Created
May 17, 2013 10:19
-
-
Save kavinyao/5598266 to your computer and use it in GitHub Desktop.
Practice code to help understand promise.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Demo code in coffeescript for Callbacks are imperative, promises are functional: Node’s biggest missed opportunity | |
# http://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-promises-are-functional-nodes-biggest-missed-opportunity/ | |
# the original version uses rsvp.Promise | |
# since I'm a control freak, I'd prefer Deferred | |
Deferred = require 'deferred' | |
slice = Array.prototype.slice | |
# transform a callback-based function to return a promise | |
# fn == function(param..., function(error, data...)) | |
promisify = (fn, receiver) -> | |
# a wrapper function of compatible interface is returned | |
return () -> | |
# omit callback even if it's passed | |
args = slice.call arguments, 0, fn.length-1 | |
dfd = new Deferred() | |
# use this callback instead | |
args.push () -> | |
results = slice.call arguments | |
error = results.shift() | |
if error | |
dfd.reject error | |
else | |
dfd.resolve.apply dfd, results | |
# do the real job | |
fn.apply receiver, args | |
return dfd.promise | |
# transform a list of promises to a promise of list | |
# the returned promise is like an array, you can access individual promises by indexing it | |
list = (promises) -> | |
list_dfd = new Deferred() | |
list_promise = list_dfd.promise | |
# this is not idiomatic, but this is just a piece of demo code, so... | |
list_promise[i] = p for p, i in promises | |
# "waits" for all promises to get resolved with a counter | |
results = [] | |
done = 0 | |
promises.forEach (promise, i) -> | |
promise.then () -> | |
# the original version does not handle multiple arguments, but here we do | |
result = slice.call arguments | |
# accumulate result | |
results[i] = result | |
if ++done == promises.length | |
list_dfd.resolve results | |
, (error) -> | |
list_dfd.reject error | |
if promises.length == 0 | |
list_dfd.resolve results | |
return list_promise | |
# test promisify | |
fs = require 'fs' | |
fs_stat = promisify fs.stat | |
# we do not handle error, so make sure the both files exist | |
paths = ['file1', 'file2'] | |
# cannot chain .forEach after .map as .forEach returns undefined | |
(stat_promises = paths.map fs_stat) | |
.forEach (promise) -> | |
promise.then (stat) -> | |
console.log stat | |
stat_promises[0].then (stat) -> | |
console.log 'this file size is', stat.size | |
# test list | |
stat_promises2 = list paths.map fs_stat | |
stat_promises2[0].then (stat) -> | |
console.log 'this file size is', stat.size | |
stat_promises2.then (stats) -> | |
console.log 'number of stats', stats.length |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment