Permalink
Browse files

chain and series

  • Loading branch information...
seanhess committed Jun 20, 2012
1 parent 590fb24 commit 45862479f4afc45eb780604f355f16b8c2c1ff12
Showing with 151 additions and 6 deletions.
  1. +37 −2 index.coffee
  2. +46 −3 index.js
  3. +68 −1 test.coffee
View
@@ -40,11 +40,46 @@ fjs = (_) ->
# like compose, but backwards. So the first method on the left is the 1st one called.
# easier for most people to understand
- chain = (funcs...) -> compose funcs.reverse()
+ chain = (funcs...) -> compose funcs.reverse()...
functions = {curry, flip, id, method, chain}
+ ## ASYNC METHODS ################################################################
+ # uses async library, but functions don't require arrays
+ # also allows you to CREATE a series
+ makeSeries = (funcs...) ->
+ index = 0
+
+ callAsync = (func, args, cb) ->
+ func args..., (err, args...) ->
+ if err? then return cb err
+ nextInSeries args..., cb
+
+ callSync = (func, args, cb) ->
+ result = func args...
+ nextInSeries result, cb
+
+ nextInSeries = (args..., cb) ->
+ func = funcs[index++]
+ # console.log "CALLING", func?, args
+ if not func? then return cb null, args...
+
+ if func.length is args.length
+ callSync func, args, cb
+ else
+ callAsync func, args, cb
+
+ # make a series and call it immediately
+ # TODO is there a way to automatically detect this, like curry does?
+ # if the FIRST one has no remaining arguments required?
+ series = (funcs..., cb) ->
+ seriesChain = makeSeries funcs...
+ seriesChain cb
+
+ async = {series, makeSeries}
+
+
## OBJECTS
# functional eqivalents to object-y stuff
# you only need these so you can write point-free and compose
@@ -141,7 +176,7 @@ fjs = (_) ->
arrays = {reverse, take}
# export!
- _.extend functions, objects, basics, us, arrays, debug
+ _.extend functions, objects, basics, us, arrays, debug, async
if define?.amd?
define(['underscore'], (_) -> fjs _)
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -3,6 +3,7 @@
# just a mocha test. Doesn't say how it's run
assert = require 'assert'
+_ = require 'underscore'
fjs = require './index'
call = fjs.call
@@ -24,7 +25,73 @@ describe 'fjs', ->
henry = {name: "henry"}
henry.getName = fjs.method name
assert.equal henry.getName(), "henry"
-
+
+
+ describe 'chain', ->
+ it 'should work like compose', ->
+ first = (array) -> array[0]
+ name = (item) -> item.name
+
+ items = [{name: "sean"}]
+
+ composeValue = _.compose(name, first)(items)
+ assert.equal composeValue, "sean", "compose incorrect"
+
+ chainValue = fjs.chain(first, name)(items)
+ assert.equal chainValue, "sean", "chain incorrect"
+
+
+ describe 'series', ->
+ it 'should do multiple async methods', (done) ->
+ getData = (cb) -> process.nextTick -> cb null, "bob"
+ getDetails = (id, cb) -> process.nextTick -> cb null, {id: id, message: "hi " + id}
+
+ fjs.series getData, getDetails, (err, data) ->
+ assert.ifError err
+ assert.ok data
+ assert.equal data.id, "bob"
+ assert.equal data.message, "hi bob"
+ done()
+
+ it 'should handle sync methods', (done) ->
+ getData = () -> "bob"
+ getDetails = (id) -> {id: id, message: "hi " + id}
+
+ fjs.series getData, getDetails, (err, data) ->
+ assert.ifError err
+ assert.ok data
+ assert.equal data.id, "bob"
+ assert.equal data.message, "hi bob"
+ done()
+
+ it 'should escape early on errors', (done) ->
+ giveError = (cb) -> cb new Error "failed", {name: "woot"}
+ dontCall = (data, cb) ->
+ throw new Error "Should not have called this method"
+ fjs.series giveError, dontCall, (err, data) ->
+ assert.ok err
+ assert.ok !data
+ done()
+
+ it 'should work with curry', ->
+ asyncAdd = curry (n, num, cb) -> cb null, num+n
+ mult = curry (n, num) -> num*n
+ myMethod = fjs.series asyncAdd(2), mult(2), (err, num) ->
+ assert.ifError err
+ assert.equal num, 8
+ done()
+
+ it 'should behave like compose and let you make one for use later', (done) ->
+ getData = (cb) -> process.nextTick -> cb null, "bob"
+ getDetails = (id, cb) -> process.nextTick -> cb null, {id: id, message: "hi " + id}
+
+ getDataDetails = fjs.makeSeries getData, getDetails
+ getDataDetails (err, data) ->
+ assert.ifError err
+ assert.ok data
+ assert.equal data.id, "bob"
+ assert.equal data.message, "hi bob"
+ done()
describe 'call', ->
it 'should call functions on the object', ->

0 comments on commit 4586247

Please sign in to comment.