JS SSE:无法在onMsg回调函数之外访问event.data? [英] JS SSE: Cannot access event.data outside of onMsg callback function?

查看:52
本文介绍了JS SSE:无法在onMsg回调函数之外访问event.data?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用three.js在浏览器中实时显示3D加速度计数据.我正在使用服务器发送事件将数据从远程服务器传输到客户端.

I am using three.js to visualize accelerometer data in real-time and in 3D on the browser. I am using server-sent-event to transfer data from the remote server to the client side.

我已经设置了three.js代码并在模拟数据上运行,并且没有呈现问题.现在,当我尝试在远程服务器上使用SSE时,我发现我只能从onMsg,onOpen,onError回调函数中读取数据

I've got three.js code up and running on simulated data and without rendering issues. Now when I try to use SSE on the remote server, I found that I can only read data from onMsg, onOpen, onError callback functions

由于这个原因,我将three.js实现放置在onMsg回调中,但是在这种情况下,浏览器一直运行,并且基本上不显示渲染,它进入了无限循环,所以我认为我不应该在Onmsg中包含任何其他函数,因此,我从SSE中分离了three.js代码,但是现在我无法从Onmsg中访问event.data并将其发送回负责渲染3D模型的main()函数中

For this reason, I placed three.js implementation inside onMsg callback, but in this case the browser was running forever and it doesn't show the render basically, it goes in an infinite loop, so I figured that I should not include any other function in Onmsg, therefore, I separated three.js code from SSE, but now I am not able to access the event.data from the Onmsg and send them back to the function main() which responsible of rendering the 3D model.

下面是我的代码:

它仅呈现3D模型(它是静态的),我可以在开发人员工具窗口上看到JSON格式的数据,但数据不会传递给3D模型.

It only renders the 3D model (it's static) and I can see the data in JSON format on the developer tool window, but the data are not passed to the 3D model.

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相当陌生,我正在尝试使所有组件正确吗?将来自Onmsg的加速度计数据(sensorValue)传递给函数main()是优先级,因此模型可以相应地在浏览器上实时移动,而不会出现任何错误或警告.非常感谢.

Do I need to use ajax callback? I am fairly new to SSE, and I am trying to get all the component right? it is a priority to pass the accelerometer data (sensorValue) from Onmsg to function main() so the model can move in real-time on the browser accordingly without any error or warning. Much appreciated.

P.S,下面是我想实现的目标

P.S, below is was I wanted to achieve

推荐答案

我们将需要在主方法的范围之外或全局范围内初始化 sunMesh ,以便以后访问它.

We will need to have sunMesh initialized either out of the scope of your main method or in the global scope to later access it.

知道 sunMesh 必须先在您的主方法中初始化,然后才能访问其位置,因此,如果您不同步创建竞争条件(例如,加载模型),则可能会创建竞争条件

Know that sunMesh would have to be initialized in your main method before you can access its position, so you might create a race condition if you don't do so synchronously (i.e. loading a model).

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函数内部进行渲染,以呈现更新(与上面的相机,场景和渲染器引用相同)

As your message events are asynchronous, you would have to render inside of your animation loop or inside of the onMsg function in order to render updates (you would do the same with camera, scene, and renderer references as above).

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();

这篇关于JS SSE:无法在onMsg回调函数之外访问event.data?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆