JavaScript 传递数据时的变量范围问题

JavaScript variable scope issue when passing data

我是 JavaScript 的新手,我一直对我认为是全局变量的范围有疑问。

这是我通过 Socket.IO 从用户那里接收数据的地方:(server.js)

var locationData = {lat: '-20', long: '20'};
var latNumber;
var longNumber;

//SocketIO data
var chat = require('express')();
var http = require('http').Server(chat);
var io = require('socket.io')(http);

io.sockets.on('connection', function (socket) {
    socket.on('new message', function (msg) {
        locationData = msg;
        latNumber = parseFloat(locationData.lat);
        longNumber = parseFloat(locationData.long);
        io.emit('message', msg.message);
    });
});

http.listen(5670, function(){
    console.log('listening on *:5670');
});

io.on('connection', function(socket){
    console.log('a user connected');
    socket.on('disconnect', function(){
        console.log('user disconnected');
    });
});

function getLat(){
    return latNumber;
}
function getLong(){
    return latNumber;
}

这是我想要接收数据的 HTML 脚本:(HelloWorld.html)

      <script type="text/javascript" src="/server.js"></script>
  <script>
    var viewer = new Cesium.Viewer('cesiumContainer');
    var citizensBankPark = viewer.entities.add({
        name : 'Test',
        position : Cesium.Cartesian3.fromDegrees(getLat(),getLong()),
        point : {
            pixelSize : 5,
            color : Cesium.Color.RED,
            outlineColor : Cesium.Color.WHITE,
            outlineWidth : 2
        },
        label : {
            text : 'Test',
            font : '14pt monospace',
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            outlineWidth : 2,
            verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
            pixelOffset : new Cesium.Cartesian2(0, -9)
        }
    });

    viewer.zoomTo(viewer.entities);
</script>

我正在尝试将 server.js 中定义和设置的 latNumber 和 longNumber 中的数据读取到 HelloWorld.html 中的位置分配中。我遇到的问题是一旦数据到达 HelloWorld.html 它是未定义的,并在浏览器中给出错误。

现在我不确定的是为什么它是未定义的。在 server.js 中记录 latNumber 和 longNumber 变量工作正常并且其中有数据。还将 getLat() getLong() 中的 return 语句更改为硬编码变量(例如 15)也可以正常工作,并将其传递到 HelloWorld.html,然后它会执行它应该执行的操作。只有当我将两者结合在一起时才会出错!

任何帮助或指点将不胜感激!谢谢!

你遇到了各种各样的问题。您的 server.js 文件看起来根本不像客户端代码,它看起来应该是 运行 通过 Node.js 连接服务器。您是否使用 Node.js 到 运行 server.js 来侦听端口 5670,正如此代码所建议的那样?

如果是这样,很好,但是删除客户端代码上的 <script src="/server.js"> 引用。您不希望客户端读取服务器的源代码(理想情况下甚至不应该提供它,但那是另一个话题)。

所以现在你有一个新问题:你的服务器有 getLatgetLon 功能,在客户端根本不存在。您需要将信息从服务器传输到客户端。

在 server.js 中,您可以添加一些代码以通过 REST 提供这些号码:

chat.get('/location', function(req, res, next) {
    var response = {
        lat: latNumber,
        lon: lonNumber
    };
    res.type('application/json');
    res.send(JSON.stringify(response));
});

此服务器代码将侦听对 URL /location 的请求,并使用包含数字的 JSON 字符串进行响应。

接下来,您的客户端代码应该从服务器异步请求这些值(这意味着我们不会在等待服务器响应时锁定浏览器的 UI)。这是这样做的:

var viewer = new Cesium.Viewer('cesiumContainer');

Cesium.loadJson('/location').then(function(data) {
    viewer.entities.add({
        name : 'Test',
        position : Cesium.Cartesian3.fromDegrees(data.lon, data.lat),
        point : {
            pixelSize : 5,
            color : Cesium.Color.RED,
            outlineColor : Cesium.Color.WHITE,
            outlineWidth : 2
        },
        label : {
            text : 'Test',
            font : '14pt monospace',
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            outlineWidth : 2,
            verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
            pixelOffset : new Cesium.Cartesian2(0, -9)
        }
    });

    viewer.zoomTo(viewer.entities);
});

在上面的代码中,loadJson returns一个获取数据的promise,我们添加了一个回调函数,在promise resolve时执行。回调接收服务器的数据作为参数,并构建一个新实体。您可以看到实体的位置是基于从服务器接收到的数据。

如果服务器的位置想法发生变化,您可能需要让客户端定期轮询新位置,或者您可以使用多种不同的技术(长轮询、服务器端推送、EventSource, WebSockets, 等) 来让客户端更新。但对于初学者来说,只需重新加载客户端页面即可看到新位置。