如何在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
相关产品推荐
相关产品推荐

