You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React.js中借助外部JS实时展示Emscripten输出的C++生成数据?

问题解决方案

1 原生HTML/JS实时渲染失效修复

问题根因

你遇到的加载完成才渲染的问题,核心是WebAssembly的同步执行逻辑占死了浏览器主线程:浏览器的DOM渲染和JS执行共享主线程,只要Wasm侧全量生成数据的同步逻辑没跑完,主线程就没有空闲时间执行重绘任务,你之前用的async、调整script位置都解决不了同步阻塞的问题。

修复步骤

  • 调整C++逻辑:将原全量返回Person数据的函数拆成分批返回的迭代逻辑,比如新增getPersonBatch(int count)函数,每次调用最多返回count条Person数据,同时返回是否还有剩余数据的标识。
  • 编译Emscripten时添加-s ASYNCIFY=1参数,支持Wasm异步执行,避免阻塞主线程。
  • JS侧修改调用逻辑,分批拉取数据,每拉取一批就主动更新DOM,每次更新后让出主线程给浏览器渲染,示例代码如下:
// 单批数据渲染逻辑
function renderPersonBatch(batchData) {
  const container = document.querySelector('#person-list-container')
  batchData.forEach(person => {
    const item = document.createElement('div')
    item.innerText = `name: ${person.name}, type: ${person.type}`
    container.appendChild(item)
  })
}

// 分批加载逻辑
async function loadAllPerson() {
  let hasRemain = true
  while(hasRemain) {
    // 调用Wasm导出的分批获取接口,每次取20条
    const result = Module.getPersonBatch(20)
    hasRemain = result.hasRemain
    renderPersonBatch(result.data)
    // 让出主线程执行渲染
    await new Promise(resolve => setTimeout(resolve, 0))
  }
}

如果需要更高的实时性,也可以直接在C++侧每生成一个Person实例,就通过EM_ASM宏调用JS侧的渲染函数,不需要等JS主动拉取。

2 React应用中实时展示实现

在React中可以基于状态更新自动触发重渲染的机制实现实时展示,React18+还可以通过过渡更新避免数据刷新阻塞用户交互,示例实现如下:

import { useState, useEffect, useTransition } from 'react'

const PersonList = () => {
  // 存储全量Person数据
  const [personList, setPersonList] = useState([])
  // 标记数据加载状态,避免更新过程中页面卡顿
  const [isLoading, startTransition] = useTransition()

  useEffect(() => {
    // 等待Wasm加载完成后再执行拉取逻辑
    if(!window.Module) return
    let hasRemain = true

    const fetchData = async () => {
      while(hasRemain) {
        const batch = window.Module.getPersonBatch(20)
        hasRemain = batch.hasRemain
        // 用startTransition包裹状态更新,低优先级执行,不阻塞用户操作
        startTransition(() => {
          setPersonList(prev => [...prev, ...batch.data])
        })
        await new Promise(resolve => setTimeout(resolve, 0))
      }
    }

    fetchData()
  }, [])

  return (
    <div className="person-list">
      {isLoading && <p>数据加载中...</p>}
      {personList.map((item, index) => (
        <div key={index} className="person-item">
          姓名:{item.name} 类型:{item.type}
        </div>
      ))}
    </div>
  )
}

export default PersonList

内容的提问来源于stack exchange,提问作者user16972560

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 21:45:04