Commits

Kenneth Jørgensen committed 4ea6ad2

Simplified the EventMessage.catch implementation to no longer return a function, but just execute. Less nice syntax, but simpler implementation and more useful.

  • Participants
  • Parent commits 3f54420

Comments (0)

Files changed (2)

File spec/core/EventMessageSpec.coffee

 			errorMsg.status = "error"
 			errorMsg.error = "Error"
 
-		it "should propagate own errors unless it has a reply handler", ->
-			# msg has an error:
-			# msg.catch (reply) =>
-			# data on `reply` should also be propagated.
+		it "should pass the call onto handler if nothing is wrong", ->
+			# Without first arg.
+			msg.catch handler
+			expect(handler.callCount).toBe 1
+			# With first arg.
+			msg.catch null, handler
+			expect(handler.callCount).toBe 2
+			msg.catch undefined, handler
+			expect(handler.callCount).toBe 3
 
-			proxyFunc = msg.catch handler
-			msg.status = "error"
-			msg.error = "Error"
-			msgNoReply.status = "error"
-			msgNoReply.error = "Error"
-			# No reply should throw the exception directly.
-			testNoReply = -> msgNoReply.catch handler
-			expect(testNoReply).toThrow "Error"
-			expect(handler.callCount).toBe 0
-			# With reply handler should pass the error along.
-			msg.catch handler
-			waitsFor (-> replier.called), "Replier never called", 100
-			runs ->
-				expect(replier.callCount).toBe 1
-				expect(handler.callCount).toBe 0
-				reply = replier.getCall(0).args[0]
-				expect(reply).toBe msg
-
-		it "should propagate reply errors unless it has a reply handler", ->
+		it "should propagate message errors unless it has a reply handler", ->
 			# reply has an error:
-			# msg.catch (reply) =>
-			# data on `reply` should also be propagated.
-
-			# No reply should throw the exception directly.
-			proxyFuncNoReply = msgNoReply.catch handler
-			testNoReply = -> proxyFuncNoReply errorMsg
-			expect(testNoReply).toThrow "Error"
-			expect(handler.callCount).toBe 0
-			# With reply handler should pass the error along.
-			proxyFunc = msg.catch handler
-			proxyFunc errorMsg
-			waitsFor (-> replier.called), "Replier never called", 100
-			runs ->
-				expect(replier.callCount).toBe 1
-				expect(handler.callCount).toBe 0
-				reply = replier.getCall(0).args[0]
-				expect(reply.status).toBe "error"
-				expect(reply.error).toBe "Error"
-
-		it "should propagate thrown errors unless it has a reply handler", ->
-			# Supplied handler threw an error:
-			# msg.catch (reply) =>
-			handler = sinon.spy -> throw new Error "Error"
-			# No reply should throw the exception directly.
-			proxyFuncNoReply = msgNoReply.catch handler
-			testNoReply = -> proxyFuncNoReply new EventMessage
-			expect(testNoReply).toThrow "Error"
-			expect(handler.callCount).toBe 1
-			# With reply handler should pass the error along.
-			proxyFunc = msg.catch handler
-			proxyFunc new EventMessage
-			waitsFor (-> replier.called), "Replier never called", 100
-			runs ->
-				expect(replier.callCount).toBe 1
-				expect(handler.callCount).toBe 2
-				reply = replier.getCall(0).args[0]
-				expect(reply.status).toBe "error"
-				expect(reply.error.split("\n")[0]).toBe "Error: Error :: Error: Error"
-
-		it "should accept an optional message and proxy errors unless it has a reply handler", ->
-			# otherMsg has an error:
-			# msg.catch otherMsg, (reply) =>
-
+			# msg.catch reply, =>
 			# No reply should throw the exception directly.
 			testNoReply = -> msgNoReply.catch errorMsg, handler
 			expect(testNoReply).toThrow "Error"
 				reply = replier.getCall(0).args[0]
 				expect(reply).toBe errorMsg
 
-		it "should accept an optional error and proxy it unless it has a reply handler", ->
-			# otherMsg *is* an error:
-			# msg.catch otherMsg, (reply) =>
+		it "should propagate real errors unless it has a reply handler", ->
+			# reply *is* an error:
+			# msg.catch reply, =>
 			error = new Error "Error"
 			# No reply should throw the exception directly.
 			testNoReply = -> msgNoReply.catch error, handler
 				expect(reply.status).toBe "error"
 				expect(reply.error.split("\n")[0]).toBe "Error: Error :: Error: Error"
 
-		it "should pass the call onyo handler if nothing is wrong", ->
-			catchFunc = msg.catch null, handler
-			catchFunc msg
-			waitsFor (-> handler.called), "Handler never called", 100
+		it "should propagate thrown errors unless it has a reply handler", ->
+			# Supplied handler threw an error:
+			# msg.catch (reply) =>
+			handler = sinon.spy -> throw new Error "Error"
+			# No reply should throw the exception directly.
+			testNoReply = -> msgNoReply.catch handler
+			expect(testNoReply).toThrow "Error"
+			expect(handler.callCount).toBe 1
+			# With reply handler should pass the error along.
+			msg.catch handler
+			waitsFor (-> replier.called), "Replier never called", 100
 			runs ->
-				expect(handler.callCount).toBe 1
-				receivedMsg = handler.getCall(0).args[0]
-				expect(receivedMsg).toBe msg
+				expect(replier.callCount).toBe 1
+				expect(handler.callCount).toBe 2
+				reply = replier.getCall(0).args[0]
+				expect(reply.status).toBe "error"
+				expect(reply.error.split("\n")[0]).toBe "Error: Error :: Error: Error"

File src/core/EventMessage.coffee

 		@reply msg
 		return @
 
-	# Returns a wrapping event handler which will automatically catch and propagate errors,
-	# removing the need to constantly check incoming messages for errors.
+	# Automatically catches and propagates errors, removing the need to constantly check incoming messages for errors.
 	# Example usage:
 	#
-	#     @send "address", msg.catch other, (reply) ->
+	#     @send "address", (reply) => msg.catch reply, =>
+	#         # your code here, reply will never be an error.
 	#
-	# In the above example, proxyErrors will check msg and other for errors, and pass them to the reply handler
-	# for msg. If no errors are detected, it will execute the supplied handler inside a try/catch block, and pass
+	# In the above example, catch will check reply for errors, and pass them to the reply handler on msg.
+	# If no errors are detected, it will execute the supplied handler inside a try/catch block, and pass
 	# any errors back through msg.
 	# If no reply handler exists on msg, errors will be rethrown, or no try/catch block will be used.
-	# other is optional and can be an EventMessage or something throwable, or undefined.
+	# The first argument is optional and can be an EventMessage, or any throwable value.
+	# If it's falsy, then it's simply ignored and handler is executed.
 	catch: (other, handler) ->
 		unless handler?
 			unless _.isFunction other
 				throw new Error "Supplied handler is not a function, #{typeof other} supplied"
 			handler = other
 			other = undefined
-		# If we don't have a reply handler, just return a passthrough function.
+		# If we don't have a reply handler, throw error directly.
 		unless _.isFunction @_replyHandler
 			# Throw error if we have one.
-			if @isError()
-				throw @error
 			if other?
-				if other instanceof EventMessage and other.isError()
-					throw other.error
+				if other instanceof EventMessage
+					if other.isError()
+						throw other.error
 				else
+					other = new Error other unless other instanceof Error
 					throw other
-			# Create and return handler.
-			return (msg) ->
-				# Pass message errors.
-				if msg.isError()
-					throw msg.error
-				# No error, pass to handler.
-				handler msg if _.isFunction handler
-		# If we have a reply handler, we need to be more sophisticated.
+			# Execute handler.
+			handler other
+		# If we have a reply handler, pass errors to it.
 		else
-			# Pass errors on self.
-			if @isError()
-				@reply @
+			# Pass supplied errors.
+			if other?
+				if other instanceof EventMessage
+					if other.isError()
+						@reply other
+				else
+					other = new Error other unless other instanceof Error
+					@replyError other
 				return
-			if other?
-				if other instanceof EventMessage and other.isError()
-					@reply other
-				else
-					@replyError other
-			# Create and return handler.
-			return (msg) =>
-				# Pass message errors.
-				if msg.isError()
-					@reply msg
-					return
-				# Setup try/catch block and execute handler.
-				if _.isFunction handler
-					try
-						handler msg
-					catch err
-						@replyError err
-						return
+			# Execute handler inside try/catch block.
+			try
+				handler other
+			catch err
+				@replyError err
 
 	# ## `isSuccess()`
 	# Returns true if this message is marked successful, which is the default state.