我正在编写一本书,教你Node.JS的基础知识,并且我创建了几个程序 - 一个响应者和一个请求者。
响应者:
cat css.html | mail -s "$(echo -e "Test\nContent-Type: text/html")" me@example.com
请求者:
"use strict";
const fs = require("fs");
const zmq = require("zmq");
const responder = zmq.socket("rep"); // Create socket to reply to client requests
// Handle incoming requests
responder.on("message", function(data) {
// Parse incoming message
let request = JSON.parse(data);
console.log("Received request to get: " + request.path);
// Read file and reply with content
fs.readFile(request.path, function(err, content) {
console.log("Sending response content");
responder.send(JSON.stringify({
content: content.toString(),
timestamp: Date.now(),
pid: process.pid
}));
});
});
// Listen on TCP port 5433
responder.bind("tcp://127.0.0.1:5433", function(err) {
console.log("Listening for zmq requesters...");
});
// Close the responder when the Node process ends
process.on("SIGINT", function() {
console.log("Shutting down...");
responder.close();
});
所以我运行启动良好的响应程序,然后像这样运行请求程序("use strict";
const zmq = require("zmq");
const filename = process.argv[2];
const requester = zmq.socket("req"); // Create request endpoint
// Handle replies from responder
requester.on("message", function(data) {
let response = JSON.parse(data);
console.log("Received response:", response);
});
requester.connect("tcp://localhost:5433");
// Send request for content
for (let i=1; i <= 3; i++) {
console.log("Sending request " + i + " for " + filename);
requester.send(JSON.stringify({
path: filename
}));
}
已经存在于文件系统中):
target.txt
奇怪的是,鉴于Node.js的单线程,我希望的输出总是:
> node requester.js target.txt
但是,有时我会这样做,但有时我会得到:
Sending request 1 for target.txt
Sending request 2 for target.txt
Sending request 3 for target.txt
Received response: { ...
这怎么可能?事件循环正在执行我的Sending request 1 for target.txt
Sending request 2 for target.txt
Received response: { ...
Sending request 3 for target.txt
循环,这应该意味着&#34;发送请求&#34;行获取输出,然后它有机会调用响应处理程序。为什么我有时会在记录第三个请求之前记录响应?
答案 0 :(得分:2)
很明显,只有在on
实施中调用提供给send
的回调时,才会出现您所看到的行为。
zmq
模块包含本机代码。它以本机代码接收响应,然后将它们提供给JavaScript主机。它收到的响应与JavaScript事件循环无关。似乎在send
实现中,如果响应可用,则调用提供给on
的回调。据推测,在send
次调用中未传递给回调的任何响应都会在下一轮通过事件循环传递。
答案 1 :(得分:-1)
在responder
函数中读取文件时,使用fs.readFile
这是一个异步非阻塞函数(它将在新线程中读取该文件)。这意味着它在接受新请求之前不会等待文件被读取。
如果您想使用同步功能,可以使用
fs.readFileSync
这将等待文件被完全读取,然后发送响应。