gpt4 book ai didi

javascript - 在Web浏览器中的JavaScript中处理异步事件处理程序中的错误

转载 作者:行者123 更新时间:2023-12-03 08:19:28 25 4
gpt4 key购买 nike

这只是处理异步事件处理程序中的错误的另一种绝望尝试。
关于此示例的注释:此处的示例与直接在浏览器中运行的示例不同。如果直接在浏览器中运行,则错误的事件侦听器均不起作用(“错误”,“未处理拒绝”)。
在Windows 10(Chrome(版本80.0.3987.163(官方内部版本)(64位))和Firefox(75.0(64位))中,它看起来与Windows 10类似。
我发现处理此问题的唯一方法是永远不要打错字。但这对我也不起作用。
这应该如何工作?

window.addEventListener("error", evt => {
console.warn("error event handler", evt);
output("error handler: " + evt.message, "yellow");
});
window.addEventListener("unhandledrejection", evt => {
console.warn("rejection event handler", evt);
output("rejection handler: " + evt.message, "green");
});
function output(txt, color) {
const div = document.createElement("p");
div.textContent = txt;
if (color) div.style.backgroundColor = color;
document.body.appendChild(div);
}

const btn = document.createElement("button");
btn.innerHTML = "The button";
btn.addEventListener("click", async evt => {
evt.stopPropagation();
output("The button was clicked");
noFunction(); // FIXME:
})
document.body.appendChild(btn);

const btn2 = document.createElement("button");
btn2.innerHTML = "With try/catch";
btn2.addEventListener("click", async evt => {
evt.stopPropagation();
try {
output("Button 2 was clicked");
noFunction2(); // FIXME:
} catch (err) {
console.warn("catch", err)
throw Error(err);
}
})
document.body.appendChild(btn2);

new Promise(function(resolve, reject) {
setTimeout(function() {
return reject('oh noes');
}, 100);
});

justAnError();
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1">
<script defer src="error-test.js"></script>


编辑-从Chrome和JS Bin添加输出
( Link to JS Bin example)
正在加载页面
Chrome/Firefox:

error handler: Script error.


JS Bin:

error handler: Uncaught ReferenceError: justAnError is not defined

rejection handler: undefined


单击左按钮
Chrome/Firefox:

The button was clicked


JS Bin:

The button was clicked

rejection handler: undefined

最佳答案

您可以为自己提供实用程序功能,用于错误报告和包装事件处理程序,如下所示:

function handleError(err) {
if (!(err instanceof Error)) {
err = Error(err);
}
output("error handler: " + err.message, "yellow");
}

function wrapHandler(fn) {
return function(evt) {
new Promise(resolve => {
resolve(fn(evt));
}).catch(e => {
handleError(e);
});
};
}

它支持 async和非 async事件处理程序。如果有一个同步错误调用 fn,它会被promise构造函数捕获,并变成对正在创建的promise的拒绝。如果没有,则将promise解析为 fn的返回值,这意味着,如果 fn返回拒绝的promise,则由 new Promise创建的promise将被拒绝。因此,无论哪种方式,错误都会转到错误处理程序。

我没有试图区分错误和拒绝,因为它们本质上是同一回事,但是如果您愿意,您可以:
function handleError(err, isRejection) {
if (!(err instanceof Error)) {
err = Error(err);
}
output("error handler: " + err.message, isRejection ? "green" : "yellow");
}

function wrapHandler(fn) {
return function(evt) {
try {
const result = fn(event);
Promise.resolve(result).catch(e => handleError(e, true));
} catch (e) {
handleError(e, false);
}
};
}

无论哪种方式,您都将设置全局处理程序以使用它并防止使用默认值:
window.addEventListener("error", errorEvent => {
handleError(errorEvent.error, false); // Remove the `, false` if you're not trying to make a distinction
errorEvent.preventDefault();
});

window.addEventListener("unhandledrejection", errorEvent => {
handleError(errorEvent.reason, true); // Remove the `, true` if you're not trying to make a distinction
errorEvent.preventDefault();
});

您可以在设置处理程序时直接使用 wrapHandler:
btn.addEventListener("click", wrapHandler(async evt => {
evt.stopPropagation();
output("The button was clicked");
noFunction(); // FIXME:
}));

...或具有另一个实用程序功能:
function addListener(elm, eventName, fn) {
const handler = wrapHandler(fn);
return elm.addEventListener(eventName, handler);
return function() {
elm.removeEventListener(handler);
};
}

...然后:
const removeBtnClick = addListener(btn, "click", async evt => {
evt.stopPropagation();
output("The button was clicked");
noFunction(); // FIXME:
});
// ...if you want to remove it later...
removeBtnClick();

实时示例-由于您的原始对象在同步错误和拒绝之间进行了区分,因此我在这里使用了该变体,但同样,它实际上是一个没有区别的区别,我不会在我自己的代码中对其进行区分:

function handleError(err, isRejection) {
if (!(err instanceof Error)) {
err = Error(err);
}
output("error handler: " + err.message, isRejection ? "green" : "yellow");
}

window.addEventListener("error", errorEvent => {
handleError(errorEvent.error, false);
errorEvent.preventDefault();
});

window.addEventListener("unhandledrejection", errorEvent => {
handleError(errorEvent.reason, true);
errorEvent.preventDefault();
});

function wrapHandler(fn) {
return function(evt) {
try {
const result = fn(event);
Promise.resolve(result).catch(e => handleError(e, true));
} catch (e) {
handleError(e, false);
}
};
}

function addListener(elm, eventName, fn) {
const handler = wrapHandler(fn);
return elm.addEventListener(eventName, handler);
return function() {
elm.removeEventListener(handler);
};
}

function output(txt, color) {
const div = document.createElement("p");
div.textContent = txt;
if (color) div.style.backgroundColor = color;
document.body.appendChild(div);
}

const btn = document.createElement("button");
btn.innerHTML = "The button";
addListener(btn, "click", async evt => {
evt.stopPropagation();
output("The button was clicked");
noFunction(); // FIXME:
});
document.body.appendChild(btn);

const btn2 = document.createElement("button");
btn2.innerHTML = "With try/catch";
addListener(btn2, "click", async evt => {
evt.stopPropagation();
try {
output("Button 2 was clicked");
noFunction2(); // FIXME:
} catch (err) {
console.warn("catch", err)
throw Error(err);
}
});
document.body.appendChild(btn2);

new Promise(function(resolve, reject) {
setTimeout(function() {
return reject('oh noes');
}, 100);
});

justAnError();
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1">

关于javascript - 在Web浏览器中的JavaScript中处理异步事件处理程序中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61080783/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com