See bottom of question for an update, based on comments/answers: This question is really about the possibility of hidden threads that do not execute callbacks.
I have a question about a potential arcane scenario involving the Node Request module in which:
A complete HTTP request is constructed and executed over the network (taking however many ms or even seconds)
... before a single function is executed at runtime on the local machine (typically in the nanoseconds?) - see below for details
I am posting this mostly as a sanity check just to make sure I am not misunderstanding something about Node / JS / Request module code.
From the examples in the Request module (see the SECOND example in that section), is this:
// Copied-and-pasted from the second example in the
// Node Request library documentation, here:
// https://www.npmjs.com/package/request#examples
// ... My ARCANE SCENARIO is injected in the middle
var request = require('request')
request(
{ method: 'GET'
, uri: 'http://www.google.com'
, gzip: true
}
, function (error, response, body) {
// body is the decompressed response body
console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity'))
console.log('the decoded data is: ' + body)
}
)
// **************************************************** //
// Is the following scenario possible?
//
// <-- HANG HANG HANG HANG HANG HANG HANG HANG HANG -->
//
// Let us pretend that the current thread HANGS here,
// but that the request had time to be sent,
// and the response is pending being received by the thread
//
// <-- HANG HANG HANG HANG HANG HANG HANG HANG HANG -->
// **************************************************** //
.on('data', function(data) {
// decompressed data as it is received
console.log('decoded chunk: ' + data)
})
.on('response', function(response) {
// unmodified http.IncomingMessage object
response.on('data', function(data) {
// compressed data as it is received
console.log('received ' + data.length + ' bytes of compressed data')
})
})
I have indicated my arcane scenario in the code snippet.
Suppose the Node process hangs at the point indicated, but that Node internally (in a hidden thread, invisible to Javascript, and therefore not calling any callbacks) WAS able to construct the request, and send it over the network; suppose the hang continues until a response (in two chunks, say) is received and waiting to be processed by Node. (This is the scenario that is certainly arcane, and that I'm not sure is even theoretically possible.)
Then suppose that the hang ends, and the Node thread above wakes up. Further, suppose that (somehow) Node was able to process the response all the way to the point of executing the callback function in the code above (yet without moving past the 'hanged' point in the code in the original code path -- again, if this is even theoretically possible).
Is the above arcane scenario theoretically possible? If so, wouldn't the data packets be received over the network and combined, ready to be passed to the callback function, before the 'data'
event was scheduled on the object? In this case, if it's possible, I would imagine that the 'data'
event would be missed.
Again, I understand that this is an arcane scenario - perhaps it's not even theoretically possible, given the internal mechanisms and coding involved.
That is my question - is the above arcane scenario, with its extremely unlikely race condition, nonetheless theoretically possible?
I ask just to make sure I'm not missing some key point. Thanks.
UPDATE: From comments & answers: I now have clarified my question. The 'arcane scenario' would require that there is a HIDDEN thread (which therefore CANNOT execute any USER code, including CALLBACKS) that constructs the request, sends it over the network, and receives the response - WITHOUT having any callbacks to trigger, including the 'data'
callback - and stops short just at the point that the 'response'
callback is ready to be called, waiting for the (single) visible JS thread to wake up.
No, this cannot happen.
Yes, there are indeed "hidden" background threads that do the work for asychronous methods, but those don't call callbacks. All execution of javascript does happen on the same thread, synchronously, sequentially. That
data
event callback will always be executed asynchronously, that is, after the current script/function ran to completion.While there could indeed already arrive packets from the network before the callback is created and attached to the event emitter, the callback that listens for packets on the lowest level is always created before the request is sent - it is an argument to the native "makeRequest" method, and is available to be called right from the beginning. So when a packet does arrive before the current script (still being occupied by constructing event emitters and attaching handlers) has finished, this event is queued up, and the callback will only be executed after the event loop is ready - on the next turn. By then, the
data
event callback is certainly created and attached.