React Native WebView注入JavaScript:异步脚本执行问题求助
解决React Native WebView中异步JavaScript脚本执行问题
我明白你遇到的困扰了——第一个带setTimeout的脚本能正常把购物车数据通过postMessage传回原生,但第二个异步fetch脚本就是跑不起来。这主要是因为异步脚本的执行逻辑和数据传递方式需要调整,下面给你一步步的解决方案:
1. 修正异步脚本逻辑,主动传递结果
你原来的异步脚本用了顶层await,而且只是return结果,但WebView的JS环境里顶层await可能不被支持,更关键的是:异步操作完成后,结果不会自动传递给原生,必须主动调用window.ReactNativeWebView.postMessage把数据发回去。
修改后的脚本应该是这样的:
async function extractItems() { try { const responsePromise = await fetch('https://www2.hm.com/tr_tr/v1/carts', { credentials: 'include'}); const response = await responsePromise.json(); // 把解析后的结果发送给原生 window.ReactNativeWebView.postMessage(JSON.stringify(response)); } catch (error) { // 捕获并发送错误信息,方便调试 window.ReactNativeWebView.postMessage(JSON.stringify({ error: error.message })); } } // 主动调用函数触发异步操作 extractItems();
2. 调整脚本注入时机,确保页面环境就绪
你之前用的injectedJavaScript是在页面开始加载时注入的,这时候可能页面的cookie还没准备好(比如用户还没完成登录会话),导致fetch请求拿不到正确的数据。更好的方式是在页面完全加载完成后,用injectJavaScript方法手动注入脚本:
修改你的WebView组件代码:
// 定义加载完成后的脚本注入逻辑 const onLoadWebUrl = () => { const asyncJsCode = ` async function extractItems() { try { const responsePromise = await fetch('https://www2.hm.com/tr_tr/v1/carts', { credentials: 'include'}); const response = await responsePromise.json(); window.ReactNativeWebView.postMessage(JSON.stringify(response)); } catch (error) { window.ReactNativeWebView.postMessage(JSON.stringify({ error: error.message })); } } extractItems(); `; // 调用WebView的injectJavaScript方法执行脚本 webViewRef.current?.injectJavaScript(asyncJsCode); }; // 调整WebView组件配置 <WebView ref={webViewRef} source={{uri: webUrl}} onNavigationStateChange={webViewState => { // setWebUrl(webViewState?.url); }} javaScriptEnabled={true} domStorageEnabled={true} startInLoadingState={true} // 移除原来的injectedJavaScript属性 onLoadEnd={() => onLoadWebUrl()} renderLoading={() => <Loading visible />} onError={() => webViewRef.current.reload()} onMessage={event => { console.log("onMessage event ==> ", event.nativeEvent.data); // 解析收到的消息 const receivedData = JSON.parse(event.nativeEvent.data); if (receivedData.error) { console.error("提取购物车数据出错:", receivedData.error); } else { if (cartUrl !== '') { onMessage(event); } } }} />
3. 额外的排查点
- 跨域与凭证问题:因为你是在hm.com的页面里fetch同域接口,所以跨域不是问题,但要确保用户已经登录(页面有有效的cookie),
credentials: 'include'会正确携带cookie,这是获取购物车数据的前提。 - WebView权限:你已经开启了
javaScriptEnabled和domStorageEnabled,这两个是必须的配置,没问题。 - 调试技巧:可以在
onMessage里打印完整的event.nativeEvent.data,看看是收到了错误信息还是空数据,方便定位问题。
内容的提问来源于stack exchange,提问作者Adeel Iftikhar
相关产品推荐
相关产品推荐

