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

Fetch跨域请求问题:JSON解析后custom_css_final返回undefined

问题排查与解决方法

核心问题分析

通过GTM加载的脚本中,fetch获取到的响应文本看似完整,但JSON.parse(a).custom_css_final返回undefined,直接在控制台运行代码却正常。主要原因及排查方向如下:

1. 响应文本存在隐藏字符(BOM/空白)

服务器返回Content-Type: text/plain,手动序列化JSON后可能存在UTF-8 BOM或前后多余空白/换行符。虽然console.log(a)显示完整,但这些隐藏字符会导致JSON.parse解析后的对象结构异常,甚至静默失败。

2. 脚本变量名笔误

代码中创建了css2变量,但后续操作的是未定义的css变量:

var css2 = document.createElement('style');
css.id = 'newcss' // 应为css2.id
css.setAttribute('type', 'text/css'); // 应为css2.setAttribute

这虽不是custom_css_final为undefined的直接原因,但会引发DOM操作异常,干扰问题判断。

3. Promise缓存与重复执行风险

getstuff是提前初始化的Promise,若GTM重复触发脚本加载,会导致Promise缓存旧响应或出现竞态条件。


解决步骤

步骤1:修复变量名笔误

将所有css变量替换为css2,确保DOM操作正确:

const dostuff = () => {
    getstuff.then((a) => {
         console.log(a);
         console.log(JSON.parse(a).custom_css_final);
         var css2 = document.createElement('style');
         css2.id = 'newcss'
         css2.setAttribute('type', 'text/css');
         document.getElementsByTagName('head')[0].appendChild(css2);

         setTimeout(function() {
            if (css2.styleSheet) {
                css2.styleSheet.cssText = JSON.parse(a).custom_css_final;
            } else {
                css2.appendChild( document.createTextNode(JSON.parse(a).custom_css_final) );
            }
         }, 300)
     })
}

步骤2:净化响应文本并添加错误捕获

在JSON.parse前去除响应文本的空白和BOM,同时添加错误捕获定位问题:

const getstuff = fetch("https://example.net/users/abc")
        .then((response) => response.text())
        .then((data) => {
            // 去除前后空白及UTF-8 BOM
            const cleanedData = data.trim().replace(/^\uFEFF/, '');
            // 验证JSON格式
            try {
                JSON.parse(cleanedData);
                return cleanedData;
            } catch (e) {
                console.error('JSON解析失败:', e, '原始数据:', data);
                throw e;
            }
        })
        .catch(err => console.error('Fetch请求失败:', err));

步骤3:修改服务器响应头为application/json

将服务器端content-type改为application/json,让fetch直接解析为JSON对象,避免手动处理文本的问题:

var data = {
    "status": false,
    "cool":"cool",
    "custom_css_final":".something { color: #00FF00; }"
}
var json = JSON.stringify(data)
const init_no_authresponse = { headers: {
 "content-type": "application/json", // 修改为application/json
 "Access-Control-Allow-Origin": "*",
 "Cache-Control": "no-store, max-age=0"
}, status: 200 }

return new Response(json, init_no_authresponse)

同步修改脚本中的fetch逻辑:

const getstuff = fetch("https://example.net/users/abc")
        .then((response) => response.json()) // 直接解析为JSON对象
        .catch(err => console.error('Fetch或解析失败:', err));

const dostuff = () => {
    getstuff.then((a) => {
         console.log(a);
         console.log(a.custom_css_final); // 无需手动parse
         var css2 = document.createElement('style');
         css2.id = 'newcss'
         css2.setAttribute('type', 'text/css');
         document.getElementsByTagName('head')[0].appendChild(css2);

         setTimeout(function() {
            if (css2.styleSheet) {
                css2.styleSheet.cssText = a.custom_css_final;
            } else {
                css2.appendChild( document.createTextNode(a.custom_css_final) );
            }
         }, 300)
     })
}

步骤4:确保脚本只执行一次

在脚本开头添加执行标记,避免GTM重复触发:

if (window.hasRunCustomCSSScript) return;
window.hasRunCustomCSSScript = true;

// 后续getstuff、dostuff代码放在此处

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:07:17