为什么我的请求和响应消息无序?

时间:2016-09-19 12:37:41

标签: javascript node.js zeromq

我正在编写一本书,教你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;行获取输出,然后它有机会调用响应处理程序。为什么我有时会在记录第三个请求之前记录响应?

2 个答案:

答案 0 :(得分:2)

很明显,只有在on实施中调用提供给send的回调时,才会出现您所看到的行为。

zmq模块包含本机代码。它以本机代码接收响应,然后将它们提供给JavaScript主机。它收到的响应与JavaScript事件循环无关。似乎在send实现中,如果响应可用,则调用提供给on的回调。据推测,在send次调用中未传递给回调的任何响应都会在下一轮通过事件循环传递。

答案 1 :(得分:-1)

responder函数中读取文件时,使用fs.readFile这是一个异步非阻塞函数(它将在新线程中读取该文件)。这意味着它在接受新请求之前不会等待文件被读取。

如果您想使用同步功能,可以使用

fs.readFileSync

这将等待文件被完全读取,然后发送响应。