I've been using NodeJS in production for a few years, and I'd agree that is probably not the best way to write an application with many layers of business logic.
That said, it's wonderful for networking, child process management and handling subscription connections (via Socket.IO, etc).
Effective evented programming does have a radically different style, and many times it boils down to tastefully drawing the line between when to bind and trigger events vs when to pass functions as arguments.
What bothered me is that I couldn't find a way to find out what code had triggered an event, or what listener was attached where. So, suddenly you're getting an error in code and you can't figure out why it's even being called, because it was attached from one of eight libraries that you picked up as to not reinvent the wheel.
...and grep emit isn't an effective solution. :)
I put a question up at SO and never received a response. http://stackoverflow.com/questions/12215273/how-are-event-tr... -- the problem itself I finally worked through, but then I ran into another. And another. And while I know my fair share of JS, and have no problem with async programming, node.js still felt awkward after a month. So long as I was in my own code, I was fine, but reasoning about code I hadn't written was painful not because of the language, but because of the flow it took.
Your question doesn't provide enough details for anyone to offer any insight, unless they've seen this exact error before.
From the error, I'd guess that you were trying to insert an email into an integer field. Check the db code in the event handlers, add some debugger calls (you can even step through code using node-inspector), done. There aren't magical solutions to application-specific errors.
Well, that's why I was asking for the general case. I couldn't find where the event was being emitted. It was somewhere in the passport code that called my code that implemented an authentication strategy, and it was calling with the email rather than the id.
And I was trying to figure out where the code was coming from in passport. The only tool for that was "grep emit". That's ridiculous.
The problem went a level deeper, but that's irrelevant to the task at hand -- I was overriding the prototype (as per the passport example) and yet my code wasn't being called, and there was some order of execution issue going on with how the initialization was interacting with express, which is when I decided to scrap the code and rethink the implementation.
And for multiple reasons, I'm rethinking that implementation in Scala instead. :)
> I'd agree that is probably not the best way to write an application with many layers of business logic.
Exactly!
Which, to me, means that it doesn't scale well. (Scaling here refers to growing the size and complexity of the program - as opposed to handling an increasing number of concurrent connections).
And, given this point, why should anyone use it as a platform to build their product on?
Just today I devised a pretty solid method to build a fairly complex node.js app while keeping it simple, maintainable and scalable.
I like the way node kind of enforces modularity, but for something as complex as the backend (super-flexible api for a frontend dbms) required for my project, it would save a lot of time/effort/ugliness-of-code to have a few objects on the global scope while allowing individual parts to be split up into their own files; e.g., a few utility functions, String/Array.prototype functions, a socket.io instance, and a redis client instance, among other things.
And to make things manageable and more extensible all while minimizing duplicate code, I ended up using John Resig's "Simple Javascript Inheritance": http://ejohn.org/blog/simple-javascript-inheritance/. I like being able to simply call Class.extend({}) to create/extend any class with access to its "super" functions. Each class is contained within its own file, of course.
The method is pretty simple:
1) Organize and order the files like you would on a client (web browser) where "global" variables are allowed.
2) Use some program to concatenate the files in the correct order into a single node app.js file for testing or production.
I'm currently using a batch script (yes, I use Windows :P) that looks something like this:
del app.js
type global.js >> app.js
type appBegin.js >> app.js
type loggur.js >> app.js
type classes\Class.js >> app.js
type classes\Client.js >> app.js
type get.js >> app.js
type post.js >> app.js
type set.js >> app.js
type socketsOn.js >> app.js
type appEnd.js >> app.js
Don't get me wrong, node's module system is used when it makes the most sense. But for what I need to do, this works perfectly. It doesn't promote spaghetti code the least bit; everything is easy to read and follow (could even call the code pretty!); it's 100% clear which objects are shared (especially since most files contain a single object or class); and as long as the method is used consistently, you get all the benefits of node/socket.io while maintaining cleanliness and scalability.
Global objects are not as much a sin as in the browser, since the environment is usually completely under your control. And of course, you wouldn't use more than a couple.
That said, it's wonderful for networking, child process management and handling subscription connections (via Socket.IO, etc).
Effective evented programming does have a radically different style, and many times it boils down to tastefully drawing the line between when to bind and trigger events vs when to pass functions as arguments.