我有一个相当复杂的设置,它要求网络浏览器本地存储填充计算机名称,以便应用程序正常工作。为了做到这一点,我从配置文件中读取:
kiosk-name: Mort
我在启动我的 node.js Web 服务器时读取了配置文件:
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();
}
}
});
所有这些都按设计工作,在未填充配置文件时默认使用计算机的 os.hostname()
。
客户端有一个基页 (index.html),它将默认页 (default.html) 加载到 iframe
中。基于 websocket 消息系统,默认页面被远程 IP 的另一个页面替换。 在旧版本的系统中(在实现配置文件之前)我们能够使用以下代码设置本地存储元素:
var win = document.getElementsByTagName('iframe')[0].contentWindow;
win.postMessage(JSON.stringify({key: 'kiosk-name', data: kioskName}), "*");
我们在收到 websocket 消息时识别 iframe,然后发送包含 JSON 字符串的 post 消息来设置本地存储元素。在这种情况下,kioskName
是一个包含硬编码值的变量。
问题
现在我们希望从配置文件中读取值,我们需要一种方法将 kioskname
传递给客户端 JavaScript,以便我们可以在 iframe< 中设置本地存储元素
.
我尝试将文件读取功能放在 export
包装器中:
(function(exports){
// file reading code here
return kioskname;
})(typeof exports === 'undefined' ? this['kioskname']={} : exports);
我遇到了一个错误:
Uncaught ReferenceError: require is not defined
在 export
函数中放置一个静态值(没有 require
允许导出函数正常工作,但不允许我读取配置需要 os
和 fs
模块的文件。
如何将从配置文件返回的值传送到可以在客户端使用它来设置本地存储元素的地方?
最佳答案
这是一个创造性的解决方案,可能并不适合所有情况,因为它涉及在 Node.js 网络服务器和客户端之间使用网络套接字。
要发送到客户端的 Websocket 设置(假设网络服务器位于“node_server
”:
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();
});
});
});
读取配置文件,然后解析并向套接字发送消息(在服务器端完成):
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);
});
NOTE this can be expanded to send multiple pieces of data via JSON to the client should the need arise. A couple of small edits are all that is needed to setup a more detailed JSON object.
在客户端接收socket消息(这段代码由客户端加载),然后解析。生成的对象被添加到此应用程序的命名空间,使该对象在需要时可用于多个脚本。
CAUTION: You should only use this methodology for objects which do not interfere with objects you may create or destroy in your scripts along the way.
// 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}), "*");
通过打开套接字并使用通过套接字传递的 JSON 字符串来填充命名空间对象,我们能够在应用程序的客户端中使用来自配置文件的服务器端信息。
关于javascript - 从配置文件获取变量到浏览器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32589759/