Permalink
Browse files

Error handling for Callback component

  • Loading branch information...
1 parent 3434a58 commit 84fcfb9148cd7fa9cb171912f4cadba4d5b30553 @bergie bergie committed Apr 3, 2013
Showing with 69 additions and 3 deletions.
  1. +20 −0 src/components/Base64Encode.coffee
  2. +28 −2 src/components/Callback.coffee
  3. +21 −1 test/Callback.coffee
@@ -1,30 +1,50 @@
+# This component receives strings or Buffers and sends them out Base64-encoded
+
noflo = require "../../lib/NoFlo"
class Base64Encode extends noflo.Component
+ description: 'Encode a string or buffer to base64'
constructor: ->
@data = null
@encodedData = ""
+ # This component has only two ports: an input port
+ # and an output port.
@inPorts =
in: new noflo.Port
@outPorts =
out: new noflo.Port
+ # Initialize an empty string for receiving data
+ # when we get a connection
@inPorts.in.on "connect", =>
@data = ""
+
+ # Process each incoming IP
@inPorts.in.on "data", (data) =>
+ # In case of Buffers we can just encode them
+ # immediately
if data instanceof Buffer
@encodedData += data.toString "base64"
return
+ # In case of strings we just append to the
+ # existing and encode later
@data += data
+
+ # On disconnection we send out all the encoded
+ # data
@inPorts.in.on "disconnect", =>
@outPorts.out.send @encodeData()
@outPorts.out.disconnect()
@data = null
@encodedData = ""
encodeData: ->
+ # In case of Buffers we already have encoded data
+ # available
return @encodedData unless @encodedData is ""
+ # In case of strings we need to encode the data
+ # first
return new Buffer(@data).toString "base64"
exports.getComponent = -> new Base64Encode
@@ -1,17 +1,43 @@
+# This component calls a given callback function for each IP it receives.
+# The Callback component is typically used to connect NoFlo with external
+# Node.js code.
+
noflo = require '../../lib/NoFlo'
+{_} = require 'underscore'
class Callback extends noflo.Component
+ description: 'Call a given function with each IP received'
constructor: ->
@callback = null
+ # We have two input ports. One for the callback to call, and one
+ # for IPs to call it with
@inPorts =
- in: new noflo.Port()
- callback: new noflo.Port()
+ in: new noflo.Port 'all'
+ callback: new noflo.Port 'function'
+ # The optional error port is used in case of wrong setups
+ @outPorts =
+ error: new noflo.Port 'object'
+ # Set callback
@inPorts.callback.on 'data', (data) =>
+ unless _.isFunction data
+ @error 'The provided callback must be a function'
+ return
@callback = data
+ # Call the callback when receiving data
@inPorts.in.on "data", (data) =>
+ unless @callback
+ @error 'No callback provided'
+ return
@callback data
+ error: (msg) ->
+ if @outPorts.error.isAttached()
+ @outPorts.error.send new Error msg
+ @outPorts.error.disconnect()
+ return
+ throw new Error msg
+
exports.getComponent = -> new Callback
View
@@ -5,9 +5,29 @@ setupComponent = ->
c = callback.getComponent()
ins = socket.createSocket()
cb = socket.createSocket()
+ err = socket.createSocket()
c.inPorts.in.attach ins
c.inPorts.callback.attach cb
- return [c, ins, cb]
+ c.outPorts.error.attach err
+ return [c, ins, cb, err]
+
+exports['test without callback'] = (test) ->
+ [c, ins, cb, err] = setupComponent()
+
+ err.on 'data', (data) ->
+ test.ok data
+ test.done()
+
+ ins.send 'Foo bar'
+
+exports['test wrong callback'] = (test) ->
+ [c, ins, cb, err] = setupComponent()
+
+ err.on 'data', (data) ->
+ test.ok data
+ test.done()
+
+ cb.send 'Foo bar'
exports["test callback"] = (test) ->
[c, ins, cb] = setupComponent()

0 comments on commit 84fcfb9

Please sign in to comment.