4 ms·
It's really not an experiment. Python's largest networking framework, Twisted, uses event-driven, non-blocking I/O with callbacks; however, Twisted implements a
by VShell 13y ago
It's really not an experiment. Python's largest networking framework, Twisted, uses event-driven, non-blocking I/O with callbacks; however, Twisted implements a number of wrappers and patterns to make it a bit more usable. (There are also a number of other commonly-used libraries for all sorts of languages which follow a similar concept; thread-oriented network programming is now a bit of a rarity in new code for things outside the "old" one-way web.)
Where in node.js, a vaguely procedural programming pattern is usually adhered to, Twisted uses a lot of objects with state to manage protocols and business logic. Many of these objects will adhere to various pre-defined interfaces within Twisted, especially when they are directly dealing with network protocols.
This means that when you're implementing that new protobuf-based protocol, you will always subclass Protocol or one of the simple Protocol subclasses in twisted.protocols.basic, implementing dataReceived() (or the relevant message-oriented function for your subclass), then create a subclass of Factory to create these protocols, then, when you want to connect, you hook up the Factory to an Endpoint.
"Callback hell" is thus mitigated by the fact that you will typically name every callback as a method on the object, and each callback can be as short as a few lines. You also don't tend to bury yourself 6 layers down waiting for a read; instead, you store a bit of state on the object, and wait for dataReceived() (or your buffer-emptying callback) to be called again.
In cases where it's still hell, for whatever reason, the @defer.inlineCallbacks decorator will help by allowing you to write code like this:
@defer.inlineCallbacks
def foo():
result = yield somethingThatReturnsDeferred()
result2 = yield somethingElse(result)
defer.returnValue(result2)
All in all, my proposal is that node.js's issue isn't that it's too opinionated; it's that it's not opinionated enough, implementing only the base layer of something which needs a lot of opinion to be usable.