获取variables从configuration文件到浏览器
我有一个相当复杂的设置,它要求networking浏览器本地存储具有计算机的名称填充,以使应用程序正常工作。 为了做到这一点,我从configuration文件中读取:
kiosk-name: Mort
我启动我的node.js Web服务器时读取configuration文件:
var filesys = require('fs'); var os = require('os'); filesys.readFile(project_path + '/kiosk.cfg', 'utf8', function(err, data) { var kioskname; if (err) { //console.log(err); kioskname = os.hostname(); } else { var configArray = data.split(':'); if('' != configArray[1]) { kioskname = configArray[1]; } else { kioskname = os.hostname(); } } });
所有这些按照devise工作,当configuration文件未被填充时,使用计算机的os.hostname()
作为默认值。
客户端具有一个基本页面(index.html),它将一个默认页面(default.html)加载到一个iframe
。 基于websocket消息系统,默认页面被来自远程IP的另一个页面replace。 在旧版本的系统中 (在实现一个configuration文件之前),我们可以用下面的代码设置本地存储元素:
var win = document.getElementsByTagName('iframe')[0].contentWindow; win.postMessage(JSON.stringify({key: 'kiosk-name', data: kioskName}), "*");
我们在接收到websocket消息时识别iframe,然后发送包含JSONstring的post消息来设置本地存储元素。 在这种情况下, kioskName
是一个包含硬编码值的variables。
问题
现在我们希望从configuration文件读取值,我们需要一种方法将kioskname
传递给客户端JavaScript,以便我们可以在iframe
设置本地存储元素。
我试图把文件读取function放在一个export
包装中:
(function(exports){ // file reading code here return kioskname; })(typeof exports === 'undefined' ? this['kioskname']={} : exports);
我得到一个错误:
未捕获的ReferenceError:require是未定义的
在export
函数中放置一个静态值(不require
允许导出函数正常工作,但不允许我读取需要os
和fs
模块的configuration文件。
我如何从configuration文件返回到我可以在客户端使用它来设置本地存储元素的地方?
这是一个创造性的解决scheme,可能并不适合每种情况,因为它涉及在Node.js Web服务器和客户端之间使用WebSocket。
Websocket安装程序发送到客户端(假设在' node_server
'的networking服务器:
var io = require('socket.io').listen(node_server); // 'attaches' socket.io to this web server io.sockets.on('connection', function (socket) { socket.emit('message', 'socket.io connected'); // output a connection message // receive JSON message and send to the websocket socket.on('message', function (data) { var address = node_server.address(); var client = dgram.createSocket("udp4"); var message = new Buffer(data); // out of the airlock! client.send(message, 0, message.length, address.port, address.address, function(err, bytes) { client.close(); }); }); });
读取configuration文件,然后parsing并发送消息到套接字(在服务器端完成):
filesys.readFile(project_path + '/kiosk.cfg', 'utf8', function(err, data) { var kioskname; if (err) { //console.log(err); kioskname = os.hostname(); } else { var configArray = data.split(':'); if('' != configArray[1]) { kioskname = configArray[1]; } else { kioskname = os.hostname(); } } // create JSON string for transmission KioskName = JSON.stringify({'config':{'kiosk-name': kioskname}}); var send_KioskName = setInterval(function(){ // could be a setTimeout for a one time send io.sockets.emit('message', KioskName.toString()); // send config file data to browser via socket }, 30000); });
注意,如果需要的话,这个扩展可以通过JSON发送多个数据给客户端。 设置更详细的JSON对象需要一些小编辑。
在客户端接收套接字消息(此代码由客户端加载),然后parsing。 将生成的对象添加到此应用程序的名称空间中,使对象在需要时可用于多个脚本。
小心:对于不会干扰您在脚本中创build或销毁的对象的对象,只能使用此方法。
// make sure a string is JSON before using function isJSON(str) { try { JSON.parse(str); return true; } catch (e) { return false; } } // set up object 'array's var kioskname = {}; // connect a socket to listen for incoming messages from the Big Giant Head var socket = io(); socket.on('message', function (data) { if(isJSON(data)) { // parse the json var json = $.parseJSON(data); // determine how to use this JSON object, multiple objects may be sent if('config' == Object.keys(json)[0]) { /* * send config data where needed - future proofed, just add cases * and namespaced objects where required */ kioskname['name'] = json.config['kiosk-name']; } } }); // attach objects to namespace window.KIOSK.kioskname = kioskname;
现在我们可以使用该对象来设置本地存储。 在我们的例子中,我们向应用程序的服务器发送消息,并用localStorage.setItem()
响应:
发布消息:
var currentFrame = document.getElementsByTagName('iframe')[0].contentWindow; currentFrame.postMessage(JSON.stringify({key: 'user-name', data: KIOSK.kioskname.name}), "*");
通过打开套接字并使用通过套接字传递的JSONstring来填充名称空间对象,我们可以使用应用程序客户机中的configuration文件中的服务器端信息。