I wasn't familiar with the Proactor design pattern. After reading a bit about it I think I understand your confusion.
Many articles online demonstrates nodejs as an example of reactor pattern
This is true.
Isn't it actually definition of proactor?
This is also true.
The difference is your point of view.
Internally, node's event loop is a blocking call (ironically). That's just the most efficient way to use non-blocking I/O. Different OSes have different functions to request the OS to wake your process up if something you are interested in happens. Due to POSIX requirements there is a cross-platform API that all modern OSes support: select()
. Node.js actually uses libuv which automatically picks the right API at compile time depending on the target platform. But for the purposes of this answer we're going to focus on select()
. So lets look at select():
numberOfEvents = select(numberOfWaits, read, write, err, timeout);
The select()
function blocks for up to timeout
milliseconds or something happens to either the read, write or err files/sockets. With just a single function the OS provides enough functionality to implement most of node.js from timers like setTimeout()
and setInterval()
to listening to network sockets. Using select()
the event loop looks something like this:
// Pseudocode:
while(1) {
evaluateJavascript();
timeout = calculateTimers();
events = select(n, read, write, err, timeout);
if (events > 0 || timersActive()) {
getCallbacks(events, read, write, err, timers());
}
}
This is basically a Reactor design pattern.
However, node hides this away in its implementation. What it exposes to Javascript programmers is a set of APIs that registers callbacks and calls those callbacks when an event happens. This is partly historical (the browser APIs was designed that way) and partly practical (it's a much more flexible architecture - almost all GUI frameworks from GTK to wxWindows to .Net works this way).
You may recognise that this sounds a lot like a Proactor design pattern. And in fact it is.
So node.js itself is an example of Reactor design pattern.
Javascript programs written in node.js are examples of Proactor design pattern.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…