JS SSE:无法在 onMsg 回调函数之外访问 event.data?
JS SSE: Cannot access event.data outside of onMsg callback function?
我正在使用 three.js 在浏览器上以实时和 3D 形式可视化加速度计数据。我正在使用 server-sent-event 将数据从远程服务器传输到客户端。
我已经 three.js 代码和 运行 模拟数据并且没有呈现问题。现在当我尝试在远程服务器上使用SSE时,我发现我只能从onMsg、onOpen、onError回调函数中读取数据
出于这个原因,我在 onMsg 回调中放置了 three.js 实现,但在这种情况下,浏览器永远 运行 并且它基本上不显示渲染,它进入无限循环, 所以我认为我不应该在 Onmsg 中包含任何其他函数,因此,我将 three.js 代码与 SSE 分开,但现在我无法从 Onmsg 访问 event.data 并将它们发送回负责渲染 3D 模型的函数 main()。
下面是我的代码:
它只渲染 3D 模型(它是静态的),我可以在开发者工具 window 上看到 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(),这样模型就可以相应地在浏览器上实时移动,而不会出现任何错误或警告。非常感谢。
P.S,下面是我想要实现的
我们需要 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();
我正在使用 three.js 在浏览器上以实时和 3D 形式可视化加速度计数据。我正在使用 server-sent-event 将数据从远程服务器传输到客户端。
我已经 three.js 代码和 运行 模拟数据并且没有呈现问题。现在当我尝试在远程服务器上使用SSE时,我发现我只能从onMsg、onOpen、onError回调函数中读取数据
出于这个原因,我在 onMsg 回调中放置了 three.js 实现,但在这种情况下,浏览器永远 运行 并且它基本上不显示渲染,它进入无限循环, 所以我认为我不应该在 Onmsg 中包含任何其他函数,因此,我将 three.js 代码与 SSE 分开,但现在我无法从 Onmsg 访问 event.data 并将它们发送回负责渲染 3D 模型的函数 main()。
下面是我的代码:
它只渲染 3D 模型(它是静态的),我可以在开发者工具 window 上看到 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(),这样模型就可以相应地在浏览器上实时移动,而不会出现任何错误或警告。非常感谢。
P.S,下面是我想要实现的
我们需要 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();