Exact nature of express.js "next()" parameter - javascript

I am very new to express.js and am reading through the documentation. I understand that the purpose of the next parameter in express middleware is to invoke the subsequent middleware function for the given route. I had assumed that next() was a function defined in the express API. However, the documentation specifically says the following:
Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next() function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.
What confuses me about next is that it doesn't appear to be defined anywhere, and so the claim that it is not part of the API is odd. The only thing I can think of is that express automatically rewrites next to be the subsequent middleware function behind the scenes (passes it as the third argument to the first middleware callback function).
My question is essentially this-- I know what next does, but exactly is it?

The next parameter is a callback provided by Express. It's a function that takes one parameter which indicates whether the next middleware function should be proceeded to.
If you pass a non-null/non-undefined value to next it indicates an error and no further processing happens.
If you pass no parameter or null then the Express continues to the next thing it will do.
To answer your question, next is a callback function provided by Express that controls when Express should move along to the next step. Its implementation is internal to Express.
Note that if your middleware is finishing the request (say by calling res.json("done!")) then you don't need to call next at all since there's nothing more to do.
As you noted, the name of the function is local at this point and can be called anything, but is usually called next.

Related

Why is express matching two routes?

I have an express API with a bunch of routes.
routes.get('/', perms('read', 'document'), r(CRUD.getAll))
routes.get('/search', perms('read', 'document'), r(CRUD.search))
routes.get('/:id', perms('read', 'document'), r(CRUD.getById))
I made sure to have /search above /:id, however, when a new request comes in to /search, I see both endpoints getting a hit (I added a console.log inside of each function).
I tried flipping the two and in that case, only /:id gets a hit.
Any idea of why this may be happening?
Think about Express routing as an array of handlers (middlewares), that have a matching rule (url). When a request comes in, the router starts checking each item in the array from the beginning. If it matches the rule, then the handler is run (some don't have conditions, so they just run on each request :)). The request chain does not end when a single url is matched! You can execute multiple handlers on the same request (and that's exactly how middlewares work).
Therefore, it really depends on what happens inside your handler. You can tell it to continue with the next item in the list, and if there's a match - the next handler will be executed (like /search and /:id, which will be search again).
Make sure you end your response. Beware if you call next and with what parameters. Post some samples of the handlers in order to debug it more :)

ExpressJs execute a callback after sending a response for every route

The scenario is to save the data in cache. We have numerous express routes written with complicated logic.
I have to find a way to save the response data in cache. I cannot go to each and every route and check whether this needs to be saved and save the data before sending the response. (If no other go, then this may be the way)
I have tried the following approaches.
https://nodejs.org/api/http.html#http_event_close_1 - using 'close' or 'finish', which fires after sending the response would do the trick. But there is no way I could get the response data in these events.
Also my node version is v0.10.31
Thought of using app.all('*', callback), but i am not sure how to catch the response data for cacheing.
Finally i thought of adding a second callback for routing, app.VERB(path, [callback...], callback), but upon returning the response in first callback, second callback is never called.
Hoping there is a solution for this, and I am stuck in this for more than a week.
The reason why adding logic into each and every routes is a tedious job is that, I need to add a configuration entry specifying which route needs to be cached with an expiry time.
Response needs to be cached in redis server. A cache key will be generated based on the route data and query strings. All those complete user specific information will be saved in a key.
So when the user hits the same route the key will be generated to check if it already exists using app.use and the data will be served without precedding to the successive middlewares.
Define a callback middleware as,
var storeResponseMiddleware = function(req, res, next) {
console.log("storing data in redis....")
..........more stuff
}
Add it to expressJs app as,
app.use(logicRoute)
app.use(storeResponseMiddleware)
Now, for all the responses storeResponseMiddleware will be called. you must call next() inside the route handlers.

Is RTCDataChannel send() a synchronous/blocking call?

I'm trying to send a file in chunks over WebRTC, and I'm wondering if I can create a callback function to be called after RTCDataChannel.send() finishes sending each chunk of the file.
Is RTCDataChannel.send() a synchronous/blocking call? If so, my callback can be executed on the line after .send().
If .send() is asynchronous/non-blocking, then this will get tricky since it doesn't seem like .send() accepts a callback function, and I want to avoid using a buffer and a timeout.
The send method is blocking. It however doesn't wait until the data went over the wire, but only puts the data on an internal buffer from where it might later (or in parallel to the script execution) be sent.
The amount of data that has not been transmitted is available as the bufferedAmount property, which will be synchronously increased by every send() call (and not be updated otherwise until the next event loop turn).
You might make your wrapper asynchronous therefore, and put a timeout before actually calling send() when the currently buffered data is "too much" (by whatever criterion you see fit).
As noted above send() is effectively async - you don't get delivery receipt.
However there is a callback onbufferedamountlow which is invoked when
the channel drains it's send buffer below a value set with bufferedAmountLowThreshold
(see MDN onbufferedamountlow)
You can use that callback to decide when to send the next chunk.
Note however that this is relatively new to the draft standard and may not be supported everywhere.

Unable to call dispose on domain at appropriate time

I'm having an issue with the domain module. Currently, I'm trying to catch any uncaught errors that are thrown in a request. Using an express middleware and domains. All requests are routed through this function before calling next and moving on to it's proper route.
app.use (req, res, next) ->
domain = createDomain()
domain.on "error", (err) ->
res.send(500)
domain.dispose()
domain.enter()
next()
The problem is, how do I dispose of the domain if an error is never thrown?
I could hoist the domain and event outside the middlewear so I don't ever have to dispose, but then I won't have access to middlewear args that I need to send a 500.
Does anyone have a better solution to how I am handling this? I've spent way too much time trying to figure out a way (and many hacky ways) to handle this. Thanks.
You do not need to call domain.dispose() if no errors occurred. The purpose of domain.dispose() is to clean up any resources that were left in an indeterminate state after jumping out out the middle of the stack, and to squelch subsequent errors that would occur due to the bad state. The inverse call of domain.enter() is simply domain.exit().
That said, browsing through the code for domains, it looks like you don't want to use domain.enter/exit this way. Each domain.enter/exit corresponds to a stack push/pop of a shared array in the domain module code. So, for example, if a second request comes in before the first one has completed, and then the first one exits before the second one does, calling exit in the first domains handler will pop the domain for the second request. It seems quite likely that enter and exit should not be split across asynchronous things.
Have you tried simply using domain.run(next)? That seems to do the trick for me. It basically enters the domain for you and then calls the callback you give to it, and then immediately exits the domain after the callback returns. Any timers or event emitters created while you are in the domain will associate themselves with that domain, as well. Event emitters then also use a similar enter-call-exit pattern when calling event handlers. It appears in the code that it is not domains that track event handlers, but rather event handlers that track domains.
In short, don't try to pair an enter with a dispose, and don't try to use enter/exit across asynchronous boundaries. Use run/bind/add/remove.

Node.js: Connecting to a Server Using Sockets

I'm just starting to play with Node.js today, and thought I'd start with what I thought would be a simple script: Connecting to a server via sockets, and sending a bit of data, and receiving it back. I'm creating a command line utility. Nothing in the browser.
An example of a server would be memcached, beanstalkd, etc. It seems the net module is the right tool for the job, but I'm still a bit fuzzy on the Node.js way of doing things. Some help would be appreciated.
Update #1
Let me see if I can break this down in into a couple smaller questions. I hate even asking questions like this, but the Node.js documentation is very sparse, and most documentation written 6 months ago is already out dated.
1) So I can use net.stream.write() to send data to the remote server, but I don't know how to get a response back. I'm not even sure how to test when write() is finished, because it doesn't take a callback.
2) A few clues on how the whole event.emit thing works would be great. I think that's really the key stone I'm missing in those whole thing.
Update #2
Here's where I'm still confused on implementing a client program. Let me diagram a typical send request => get response system:
1) I bind callbacks to the net module to get responses and other events, including the necessary bindings to get a response from the server.
2) I use stream.write() to send a request to the server.
3) I then do nothing, because my bound "data" event will get the response from the server.
Here's where things get tricky. Suppose I call stream.write() twice before my bound "data" event is called. Now I have a problem. When the "data" event does happen, how do I know which of the 2 requests it's a response for? Am I guaranteed that responses will take place in the same order as requests? What if responses come back in a different order?
First of all, let's make clear what a EventEmitter is. JavaScript and therefore Node.js are asynchronous. That means, instead of having to wait for incoming connections on a server object, you add a listener to the object and pass it a callback function, which then, "as soon" as the event happens, gets executed.
There's still waiting here and there going on in the background but that has been abstracted away from you.
Let's take a look at this simple example:
// #1) create a new server object, and pass it a function as the callback
var server = net.createServer(function (stream) {
// #2) register a callback for the 'connect' event
stream.on('connect', function () {
stream.write('hello\r\n'); // as
});
// #3) register a callback for the 'data' event
stream.on('data', function (data) {
stream.write(data);
});
// #4) register a callback for the 'end' event
stream.on('end', function () {
stream.write('goodbye\r\n');
stream.end();
});
});
// #5) make the server listen on localhost:8124
server.listen(8124, 'localhost');
So we create the server and pass it the callback function, this function is not yet executed. Passing the function here is basically a shortcut for adding a listener for the connection event of the server object. After that we start the server at #5.
Now what happens in the case of an incoming connection?
Since the function we passed to createServer was bound to the connection event, it now gets executed.
It adds the connect, data and end event listeners to the stream object (which represents the individual connection) by hooking up callbacks for the events.
After that, the stream fires the connect event, therefore the function passed at #2 gets executed and writes hello\r\n to the stream. How does the function know which stream it should write to? Closures are the answer, the function inherits the scope it was created in, therefore inside the function stream is still referencing to the individual connection that triggered this very callback we're in right now.
Now the client sends some data over the connection, which makes the stream object call its data event, since we bound a function to this event at #3 we now echo the incoming data back to the client.
In case the client closes the connection, the function we've bound at #4 gets called, which writes goodbye\r\n and after that closes the connection from our side.
Does this make things a little bit more clear? Well it definitely makes the whole thing a lot easier. Node is, just as well as JavaScript is inside Browsers, single threaded. There's only one thing happening at a given point time.
To describe it simple, all these callbacks end up in a global queue and are then called one after another, so this queue may(abstracted) look like this:
| connection event for a new stream
| data event for stream #12
| callback set via setTimeout
v close event of yet another stream
These are now get executed top to bottom, nothing will ever happen in between those. There's no chance, that while you're doing something in the callback bound to the data event, something will other will happen and magically change the state of the system. Even if there is a new incoming connection on the server, its event will get queued up and it will have to wait until everything before it, including the data event you're currently in, finishes.

Categories

Resources