javascript - JS SSE:无法在 onMsg 回调函数之外访问 event.data?
问题描述
我正在使用 three.js 在浏览器上实时和 3D 可视化加速度计数据。我正在使用 server-sent-event 将数据从远程服务器传输到客户端。
我已经在模拟数据上启动并运行了三个.js 代码,并且没有呈现问题。现在尝试在远程服务器上使用SSE,发现只能从onMsg、onOpen、onError回调函数中读取数据
出于这个原因,我在 onMsg 回调中放置了 three.js 实现,但在这种情况下,浏览器一直在运行,它基本上不显示渲染,它进入无限循环,所以我认为我不应该包含任何其他Onmsg 中的函数,因此,我将 three.js 代码从 SSE 中分离出来,但现在我无法从 Onmsg 访问 event.data 并将它们发送回负责渲染 3D 模型的函数 main()。
下面是我的代码:
它只渲染 3D 模型(它是静态的),我可以在开发人员工具窗口上看到 JSON 格式的数据,但数据不会传递给 3D 模型。
function main() {
const canvas = document.querySelector('#canvas');
const renderer = new THREE.WebGLRenderer({ canvas });
var context = canvas.getContext("2d");
const fov = 70;
const aspect = 2;
const near = 20;
const far = 500;
const color = 0xFFFFFF;
const intensity = 1;
const size = 10;
const divisions = 10;
const objects = [];
const radius = 3;
const widthSegments = 3;
const heightSegments = 3;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
const sphereGeometry = new THREE.BoxGeometry(radius, widthSegments, heightSegments);
const sunMaterial = new THREE.MeshBasicMaterial({ color: "green", wireframe: false });
const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial)
const light = new THREE.PointLight(color, intensity);
// const gridHelper = new THREE.GridHelper(200000, 10000);
camera.position.z = 0;
camera.position.x = 100;
camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);
const scene = new THREE.Scene();
{
const color = 0x00afaf;
const intensity = 10;
const light = new THREE.PointLight(color, intensity);
scene.add(light);
// gridHelper.geometry.rotateY(Math.PI / 2);
// scene.add(gridHelper);
// scene.add(light);
}
function resizeRendererToDisplaySize() {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function resizeToClient() {
const needResize = resizeRendererToDisplaySize()
if (needResize) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
}
var cubeAxis = new THREE.AxesHelper(10);
sunMesh.add(cubeAxis);
sunMesh.scale.set(5, 5, 5)
scene.add(sunMesh);
scene.background = new THREE.Color(0.22, 0.23, 0.22);
function render() {
sunMesh.position.x = 100;
// sunMesh.rotation.y = -70.68;
}
resizeToClient();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function onMsg(event) {
// console.log(`[message] Data received from server: ${event.data}`);
// console.log("event.data = " + JSON.parse(event.data));
var received_msg = event.data;
var obj = JSON.parse(JSON.parse(received_msg));
if (obj !== null) {
if (
obj.hasOwnProperty("DataMapChangedObjectsAddressValue") &&
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"] !==
undefined
) {
let sensorAddr =
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"];
let sensorValue =
obj["DataMapChangedObjectsAddressValue"][0]["Value"];
//Accelerometer X Axis
//if(sensorAddr === this.despToAddrMap.get("Accelerometer X Axis Data")){
if (sensorAddr === 3) {
console.log((sensorValue / 16384) * 500);
}
}
}
}
function onOpen(e) {
console.log("SSE connected");
}
function onError(e) {
// console.log(`[error] ${error.message}`);
if (e.eventPhase == EventSource.CLOSED) this.source.close();
if (e.target.readyState == EventSource.CLOSED) {
console.log("SSE Disconnected");
} else if (e.target.readyState == EventSource.CONNECTING) {
console.log("SSE Connecting ...");
}
}
function StartRetrieveLiveData() {
if (!!window.EventSource) {
this.source = new EventSource("/sse");
} else {
console.log("Your browser doesn't support SSE");
}
this.source.addEventListener("message", e => this.onMsg(e));
this.source.addEventListener("open", e => this.onOpen(e), false);
this.source.addEventListener("error", e => this.onError(e), false);
// Add here (only mozilla)
main();
// Add here
}
StartRetrieveLiveData();
我需要使用ajax回调吗?我对 SSE 还很陌生,我正在努力让所有组件都正确?将加速度计数据(sensorValue)从 Onmsg 传递到函数 main() 是一个优先事项,因此模型可以在浏览器上相应地实时移动,而不会出现任何错误或警告。非常感激。
PS,下面是我想要实现的
解决方案
我们需要在sunMesh
您的 main 方法范围之外或在全局范围内进行初始化,以便以后访问它。
知道sunMesh
必须在您的 main 方法中初始化它才能访问它的位置,因此如果您不同步执行此操作(即加载模型),您可能会创建竞争条件。
let sunMesh;
function main() {
sunMesh = new THREE.Mesh(...)
}
function onMsg(event) {
const sensorValue = event.data;
sunMesh.position.x = sensorValue;
}
// or, in the global scope (I'd try to avoid this)
function main() {
window.sunMesh = new THREE.Mesh(...)
}
function onMsg(event) {
const sensorValue = event.data;
window.sunMesh.position.x = sensorValue;
}
编辑:由于您的消息事件是异步的,因此您必须在动画循环内或 onMsg 函数内进行渲染才能渲染更新(您可以对相机、场景和渲染器引用进行上述操作)。
let sunMesh;
function main() {
const canvas = document.querySelector('#canvas');
const renderer = new THREE.WebGLRenderer({ canvas });
var context = canvas.getContext("2d");
const fov = 70;
const aspect = 2;
const near = 20;
const far = 500;
const color = 0xFFFFFF;
const intensity = 1;
const size = 10;
const divisions = 10;
const objects = [];
const radius = 3;
const widthSegments = 3;
const heightSegments = 3;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
const sphereGeometry = new THREE.BoxGeometry(radius, widthSegments, heightSegments);
const sunMaterial = new THREE.MeshBasicMaterial({ color: "green", wireframe: false });
sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial)
const light = new THREE.PointLight(color, intensity);
// const gridHelper = new THREE.GridHelper(200000, 10000);
camera.position.z = 0;
camera.position.x = 100;
camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);
const scene = new THREE.Scene();
{
const color = 0x00afaf;
const intensity = 10;
const light = new THREE.PointLight(color, intensity);
scene.add(light);
// gridHelper.geometry.rotateY(Math.PI / 2);
// scene.add(gridHelper);
// scene.add(light);
}
function resizeRendererToDisplaySize() {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function resizeToClient() {
const needResize = resizeRendererToDisplaySize()
if (needResize) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
}
var cubeAxis = new THREE.AxesHelper(10);
sunMesh.add(cubeAxis);
sunMesh.scale.set(5, 5, 5)
scene.add(sunMesh);
scene.background = new THREE.Color(0.22, 0.23, 0.22);
function render() {
renderer.render(scene, camera);
}
resizeToClient();
requestAnimationFrame(render);
}
function onMsg(event) {
// console.log(`[message] Data received from server: ${event.data}`);
// console.log("event.data = " + JSON.parse(event.data));
var received_msg = event.data;
var obj = JSON.parse(JSON.parse(received_msg));
if (obj !== null) {
if (
obj.hasOwnProperty("DataMapChangedObjectsAddressValue") &&
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"] !==
undefined
) {
let sensorAddr =
obj["DataMapChangedObjectsAddressValue"][0]["DataMapAddress"];
let sensorValue =
obj["DataMapChangedObjectsAddressValue"][0]["Value"];
//Accelerometer X Axis
//if(sensorAddr === this.despToAddrMap.get("Accelerometer X Axis Data")){
if (sensorAddr === 3) {
console.log((sensorValue / 16384) * 500);
}
sunMesh.position.x = sensorValue;
}
}
}
function onOpen(e) {
console.log("SSE connected");
}
function onError(e) {
// console.log(`[error] ${error.message}`);
if (e.eventPhase == EventSource.CLOSED) this.source.close();
if (e.target.readyState == EventSource.CLOSED) {
console.log("SSE Disconnected");
} else if (e.target.readyState == EventSource.CONNECTING) {
console.log("SSE Connecting ...");
}
}
function StartRetrieveLiveData() {
if (!!window.EventSource) {
this.source = new EventSource("/sse");
} else {
console.log("Your browser doesn't support SSE");
}
this.source.addEventListener("message", e => this.onMsg(e));
this.source.addEventListener("open", e => this.onOpen(e), false);
this.source.addEventListener("error", e => this.onError(e), false);
// Add here (only mozilla)
main();
// Add here
}
StartRetrieveLiveData();
推荐阅读
- .net - 如何在其他服务器上保留缓存
- linux - max14830 带比格骨黑色
- unity3d - Unity UI OnEndDrag 中的错误-pointerCurrentRaycast?
- node.js - 如何使用 hapi npm 配置 index.js 进行部署
- react-native - 如何在 ReactNative 的 SectionList 中实现 TextInput?
- python - 为什么 z 检验表明 2 个看起来相似的分布存在显着差异(假设检验)
- django - 如何确保 app2 无法访问我的 django app1 url
- azure-data-factory-2 - 数据工厂中的 Python 脚本
- php - 自定义帖子类型的分页不起作用 - WordPress
- c# - 依赖注入的 DbContext 始终为空