【问题标题】:Getting variables From a config file to the browser从配置文件获取变量到浏览器
【发布时间】:2015-09-15 15:18:34
【问题描述】:

我有一个相当复杂的设置,需要网络浏览器本地存储填充计算机名称,以便应用程序正常工作。为了做到这一点,我从配置文件中读取:

kiosk-name: Mort

我在启动 node.js 网络服务器时读取了配置文件:

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 和@ 的配置文件987654334@ 个模块。

如何将配置文件返回的值保存到可以在客户端使用它来设置本地存储元素的位置?

【问题讨论】:

    标签: javascript node.js iframe


    【解决方案1】:

    这是一个创造性的解决方案,可能并不适合所有情况,因为它涉及在 Node.js Web 服务器和客户端之间使用 websocket。

    Websocket 设置发送到客户端(假设 Web 服务器位于 '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);
    
    });
    

    注意可以扩展,以便在需要时通过 JSON 向客户端发送多条数据。只需进行一些小的编辑即可设置更详细的 JSON 对象。

    在客户端接收socket消息(此代码由客户端加载),然后解析。生成的对象将添加到此应用程序的命名空间中,从而使该对象在需要时可用于多个脚本。

    注意:您应该只对不会干扰您可能在脚本中创建或销毁的对象的对象使用此方法。
    // 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 字符串来填充一个命名空间对象,我们能够使用来自应用程序客户端配置文件的服务器端信息。

    【讨论】:

      猜你喜欢
      • 2019-10-10
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 2011-02-04
      相关资源
      最近更新 更多