如何在JavaScript Stream Deck插件中捕获HTTP错误并写入日志文件
解决Stream Deck插件中无法捕获网络错误详情的问题
我明白你的困扰——浏览器出于安全限制,不会把DNS解析失败(比如ERR_NAME_NOT_RESOLVED)这类底层网络错误的具体信息暴露给JavaScript回调,这就是为什么你在xhr.onerror里只能拿到状态码0,window.onerror也完全不触发的原因。下面给你几个可行的解决方案:
一、先搞清楚为什么拿不到详细错误
- 当发生DNS失败、跨域拦截这类底层网络级错误时,浏览器为了避免泄露敏感网络信息,会刻意隐藏具体错误码,只返回状态0,不会给JS任何额外详情。
window.onerror只负责捕获JavaScript执行时的错误(比如语法错误、未定义变量),网络请求错误不属于这个范畴,所以不会触发。如果要监听资源加载错误(比如图片、脚本加载失败),需要用带捕获参数的addEventListener,但这对XHR请求也没用。
二、可行的错误记录方案
1. 利用XHR的onloadend事件补充上下文
虽然拿不到具体错误码,但可以结合状态0、请求URL、时间戳等信息生成有价值的日志,足够用于调试:
var xhr = new XMLHttpRequest(); xhr.onloadend = function() { if (this.status === 0) { // 构建自定义错误日志 const errorLog = { timestamp: new Date().toISOString(), requestUrl: this.responseURL || 'http://badurl12345', errorType: '网络错误(大概率是DNS解析失败或跨域限制)', statusCode: this.status }; console.log('捕获到网络错误:', errorLog); // 这里调用日志写入逻辑 writeErrorToFile(errorLog); } }; xhr.open('GET', 'http://badurl12345'); xhr.send();
2. 结合Stream Deck的Electron环境写入日志
Stream Deck插件运行在Electron环境下,你可以直接使用Node.js的fs模块来写入自定义日志文件:
const fs = require('fs'); const path = require('path'); // 定义日志文件路径(比如插件专属的日志目录) const logFilePath = path.join( process.env.APPDATA, 'Elgato/StreamDeck/Plugins/你的插件ID/logs/network_errors.log' ); function writeErrorToFile(errorDetails) { // 格式化日志条目 const logEntry = `${new Date().toISOString()} - ${JSON.stringify(errorDetails)}\n`; // 追加写入日志 fs.appendFile(logFilePath, logEntry, (err) => { if (err) console.error('写入日志失败:', err); }); }
3. 用Fetch API优化错误捕获逻辑
Fetch的错误处理更简洁,虽然同样拿不到具体错误码,但可以更清晰地捕获网络错误场景:
fetch('http://badurl12345') .then(response => { if (!response.ok) { throw new Error(`HTTP错误!状态码: ${response.status}`); } return response.text(); }) .catch(error => { const errorLog = { timestamp: new Date().toISOString(), requestUrl: 'http://badurl12345', errorMessage: error.message, errorStack: error.stack }; writeErrorToFile(errorLog); });
三、关于window.onerror的补充
如果需要捕获其他类型的资源加载错误(比如插件内的图片、脚本加载失败),可以用下面的方式监听,但注意这依然无法捕获XHR的网络错误:
window.addEventListener('error', (event) => { if (event.target instanceof HTMLScriptElement || event.target instanceof HTMLImageElement) { console.log('资源加载错误:', event.message, event.filename); writeErrorToFile({ message: event.message, resourceUrl: event.filename, errorType: '资源加载错误' }); } }, { capture: true });
内容的提问来源于stack exchange,提问作者Elliott B
相关产品推荐
相关产品推荐

