0

嗨,我正在编写一个简单的 nodejs 推送通知服务器,它基本上是读取动态编辑的 json 文件并将其内容推送到客户端。

更新:如果我删除类似的数据 = JSON.parse(data); 有人可以澄清一下吗?

我每 5 秒使用 python 编辑一次 json 文件。但是每次我运行 python 循环来编辑文件时,节点服务器都会崩溃。但是,如果我在 while 循环中单独运行相同的代码,节点服务器就可以正常工作。

节点服务器出现以下错误

   debug - cleared heartbeat timeout for client c_u5Oi1eGnwaDerGREMD
   debug - set heartbeat interval for client c_u5Oi1eGnwaDerGREMD
{"sample": {"name": "Shubhanshu Mishra100", "networks": ["facebook", "twitter",
"linkedin"]}}
   debug - websocket writing 5:::{"name":"notification","args":[{"sample":{"name
":"Shubhanshu Mishra100","networks":["facebook","twitter","linkedin"]},"time":"2
012-10-09T11:24:55.588Z"}]}
{"sample": {"name": "Shubhanshu Mishra100", "networks": ["facebook", "twitter",
"linkedin"]}}
   debug - websocket writing 5:::{"name":"notification","args":[{"sample":{"name
":"Shubhanshu Mishra100","networks":["facebook","twitter","linkedin"]},"time":"2
012-10-09T11:24:55.589Z"}]}
{"sample": {"name": "Shubhanshu Mishra200", "networks": ["facebook", "twitter",
"linkedin"]}}
   debug - websocket writing 5:::{"name":"notification","args":[{"sample":{"name
":"Shubhanshu Mishra200","networks":["facebook","twitter","linkedin"]},"time":"2
012-10-09T11:25:00.598Z"}]}
{"sample": {"name": "Shubhanshu Mishra200", "networks": ["facebook", "twitter",
"linkedin"]}}
   debug - websocket writing 5:::{"name":"notification","args":[{"sample":{"name
":"Shubhanshu Mishra200","networks":["facebook","twitter","linkedin"]},"time":"2
012-10-09T11:25:00.619Z"}]}


undefined:0

^
SyntaxError: Unexpected end of input
    at Object.parse (native)
    at F:\My Codes\NodeJs\PushNotification\server.js:25:16
    at fs.readFile (fs.js:176:14)
    at Object.oncomplete (fs.js:297:15)

我正在使用 Node.js 中的以下代码读取 response.json 文件

io.sockets.on('connection', function(socket){
    fs.watch('response.json', function(curr, prev){
        fs.readFile('response.json', 'utf8', function(err, data){
            if(err) throw err;
            console.log(data);
            data = JSON.parse(data);
            data.time = new Date();

            socket.volatile.emit('notification', data);
        });

    });
});

更新:如果我删除类似的数据 = JSON.parse(data); 有人可以澄清一下吗?

当我单独调用我的python脚本时,我的python代码是:

import json
import time

jsonStr = {
    "sample": {
        "name": "Shubhanshu Mishra",
        "networks": [
                "facebook",
                "twitter",
                "linkedin"
        ]
    }
}

i = 0
jsonStr['sample']['name'] = "Shubhanshu Mishra" + str(i);
fStr = json.dumps(jsonStr)
with open('response.json', 'w') as f:
        f.write(fStr)
f.closed

但是,当我将上面的相同代码包装在一个睡眠时间为 5 秒的 while 循环中时,我得到了上述错误。我的 while 循环代码是:

while True:
    i += 100
    print i
    jsonStr['sample']['name'] = "Shubhanshu Mishra" + str(i);
    fStr = json.dumps(jsonStr)
    #f = open("response.json", "w")
    with open('response.json', 'w') as f:
        f.write(fStr)
    f.closed
    #f.write(fStr)
    print "Written to file: " + fStr
    #f.close()
    time.sleep(5)

我的完整代码可见:https ://github.com/napsternxg/PushNotification

4

1 回答 1

2

发生的情况是这样的:Python 通过首先清除文件来写入文件,然后写入字符串。一旦文件被清除,节点就会触发事件,并读取(空)文件。然后,尝试 JSON 解析一个空字符串,你会得到错误。

问题是,当您手动运行简单的 python 脚本(没有 while 循环)时,为什么不会发生这种情况。我不确定,但我认为这与各种竞争条件有关,主要区别在于循环中,在写入文件之后,它会打印一些东西,然后睡觉一些,在另一个万一它就退出了。如果您在手动空闲脚本中添加打印和睡眠,如果您得到相同的(崩溃)行为,我一点也不会感到惊讶。

那么,如何解决这个问题。一个不太好,但可行的方法是添加一个小睡眠,以允许写入完成:

io.sockets.on('connection', function(socket){
    fs.watch('response.json', function(curr, prev){
      setTimeout(function () {
        fs.readFile('response.json', 'utf8', function(err, data){
            if(err) throw err;
            console.log(data);
            data = JSON.parse(data);
            data.time = new Date();

            socket.volatile.emit('notification', data);
        });
      }, 50);
    });
});

由于我希望您从 中获得 2 个回调,因此fs.watch最好通过下划线对它们进行去抖动(实际上忽略第一个):

var _ = require("underscore");
io.sockets.on('connection', function(socket){
    fs.watch('response.json', _.debounce(function(curr, prev){
        fs.readFile('response.json', 'utf8', function(err, data){
            if(err) throw err;
            console.log(data);
            data = JSON.parse(data);
            data.time = new Date();

            socket.volatile.emit('notification', data);
        }), 50);
    });
});

如果您忽略该错误,我认为它甚至会像您期望的那样工作(因为在来自 的第二个回调中fs.watch,该文件将包含正确的数据)。

但是,最后,我认为这不是将新数据注入正在运行的程序中的方法。我会使用以下方法之一:

  • 使用消息队列系统
  • 使用命名管道
  • 在 sighup 上重新加载配置文件(而不是在它们更改时)
于 2012-10-09T17:09:15.470 回答