Трудно, чтобы код выполнялся в полном соответствии с идеей разработчика. Всегда возникают непредвиденные ситуации. Очевидно, что это не то, чем должен заниматься квалифицированный разработчик. Особенно важно обрабатывать, собирать и анализировать информацию об ошибках. статья обсуждает эту часть содержания.
Для студентов, изучающих внешний интерфейс, ошибки часто блокируют работу программы и выдают ошибку, доставляя пользователям крайне неприятное впечатление. Если мы сможем заранее подготовиться к ошибкам и отреагировать на их обнаружение, мы сможем предоставить пользователям лучший опыт. Вы также можете активно обнаруживать некоторые скрытые проблемы кода посредством сбора и анализа информации об ошибках.Вы можете получить все виды информации в первый раз, не дожидаясь, пока пользователи обойдут большой круг, чтобы сообщить вам об ошибках.
коллекция клиентов
window.onerror
window.onerror будет вызываться глобально при возникновении ошибки времени выполнения JavaScript или синтаксической ошибки.
window.onerror = (msg, url, lineNum, colNum, err) => {
console.log(`错误发生的异常信息(字符串):${msg}`)
console.log(`错误发生的脚本URL(字符串):${url}`)
console.log(`错误发生的行号(数字):${lineNum}`)
console.log(`错误发生的列号(数字):${colNum}`)
console.log(`错误发生的Error对象(错误对象):${err}`)
};
Примечание. Здесь мы можем получить ошибку, которая была выдана и не обнаружена. И не может получить ошибки, такие как обещания.
Все не будет гладко.Когда многие студенты пытаются снова, они должны обнаружить, что они могут получить только один.Script errorТам нет сообщения, URL-адреса и другой информации о самой ошибке, а как lineNum, так и colNum равны 0, что не является сообщением об ошибке, когда возникает настоящая ошибка.
Причина в том, что браузер находится под ограничением той же политики происхождения. Из соображений безопасности браузер выдает исключение во внешнем скрипте, не относящемся к тому же домену, на который ссылается страница.В настоящее время у страницы нет разрешения на получение сведений об исключении, и будет выведено сообщение об ошибке Script error. В Chrome есть такой механизм безопасности.Он не выставит вам полное сообщение об ошибке между доменами.Это происходит только в chrome.В Firefox и Safari вы обычно можете получить полное сообщение об ошибке.
Решить ошибку скрипта
Если вы хотите решить эту проблему, вы можете использовать механизм совместного использования ресурсов между источниками (CORS).
- Добавьте атрибут crossorigin в тег скрипта на странице.
<!-- 增加 crossorigin 属性后,浏览器将自动在请求头中添加一个 Origin 字段,告诉服务器自己的来源,服务器再判断是否返回 -->
<script src="http://xxx.xxx.xxx.x/xxx.js" crossorigin></script>
- Добавьте Access-Control-Allow-Origin в заголовок ответа, чтобы обеспечить совместное использование ресурсов между источниками.
Вы можете решить, нужно ли вам решать эту проблему в соответствии с вашими потребностями, и собрать эту часть неполной информации об ошибке.
unhandledrejection
Как упоминалось выше, ошибки в Promise не могут быть перехвачены с помощью try...catch и window.onerror. В настоящее время нам нужно необработанное отклонение, чтобы помочь нам поймать эту часть ошибки.
window.addEventListener('unhandledrejection', (e) => {
console.log(`Promise.reject()中的内容,告诉你发生错误的原因:${e.reason}`);
console.log(`Promise对象 :${e.promise}`);
});
Стоит отметить, что совместимость unandandreject не очень хорошая, картина кавиция прилагается ниже
console.error
console.error часто рассматривается как распечатанный журнал, предсказуемые ошибки, ошибки, которые были обнаружены, вещи, которые были обработаны. Поэтому его часто игнорируют и не решают.
Следующий код всегда очень распространен, он делает много вещей, используя большую попытку... поймать, перехватив исключение, а затем нажав console.error, чтобы завершить работу, возможно, обработка исключения была выполнена, ошибка обнаружена , а ошибка не допускается.Программа вылетает, но если это тоже неотъемлемая часть сбора ошибок
try {
// some code
} catch (err) {
console.error(err)
}
Поэтому мы немного модифицируем console.error, чтобы мы могли что-то делать каждый раз, когда запускается console.error, например сообщать системе сбора ошибок.
console.error = (func => {
return (...args) => {
// 在这里就可以收集到console.error的错误
// 做一些事情
func.apply(console, args);
}
})(console.error);
addEventListener('error')
Большой парень с первого взгляда указал на мои недостатки, подошел к изучению и дополнил это содержание. Спасибо @Dikaplio 🙏
На стороне клиента не удалось загрузить некоторые статические ошибки ресурсов, изображения, css, скрипты. Ни один из упомянутых выше методов не может быть захвачен.
Метод 1: захват OneRror
<script src="https://cdn.xxx.com/js/test.js" onerror="errorHandler(this)"></script>
<link rel="stylesheet" href="https://cdn.xxx.com/styles/test.css" onerror="errorHandler(this)">
Таким образом, вы можете получить ошибки этих статических ресурсов, но недостатки также очевидны, и проникновение кода сильнее, что не является хорошим способом.
Способ 2: addEventListener('ошибка')
В большинстве случаев addEventListener('error') похож на window.onerror. В браузере есть два механизма событий: захват и всплытие.Эти два метода приводят к ошибкам при захвате и воспроизведении соответственно.
Но для события ошибки загрузки ресурса canBubble: false, поэтому window.onerror, как и должно быть, не может получить ошибку загрузки ресурса, а addEventListener может получить ошибку. Но после получения ошибки вам нужно просто отличить, является ли это ошибкой загрузки ресурса или другими ошибками, поскольку этот метод также может обнаруживать ряд других ошибок, таких как синтаксические ошибки.
Метод также очень прост, между ними есть очевидная разница, другие распространенные ошибки будут иметь поле сообщения, ошибки загрузки ресурсов не имеют этого поля, поэтому, пока этот фрагмент кода выполняется перед всеми ресурсами, вы можете получить это неправильно.
window.addEventListener('error', (errorEvent) => {
console.log(errorEvent)
cosnole.log(errorEvent.message)
}, true)
Следует отметить, что здесь получено событие события, в отличие от предыдущего, то, что получено, не является объектом ошибки.
коллекция серверов
Сбор на сервере Node фактически аналогичен сбору на клиенте, но есть некоторые различия в методах.
uncaughtException
Через глобальную обработку Node фиксируются все необработанные ошибки.Это последний уровень уровня, а суть операции.Если ее не обрабатывать, то это часто приводит к сбою программы.
process.on('uncaughtException', err => {
//do something
});
unhandledRejection
В Node ошибки в промисах также не могут быть перехвачены с помощью try...catch или uncaughtException. В настоящее время нам нужно unhandledRejection, чтобы помочь нам поймать эту часть ошибки.
process.on('unhandledRejection', err => {
//do something
});
console.error
console.error = (func => {
return (...args) => {
// 在这里就可以收集到console.error的错误
// 做一些事情
func.apply(console, args);
}
})(console.error);
Обработка исключений с помощью фреймворка (на примере koa)
На стороне Node мы часто можем использовать фреймворк для захвата ошибок. Например, koa может фиксировать ошибки на уровне фреймворка с помощью app.on error. Он также фиксирует ошибки, которые не перехвачены внутри. Ошибки промисов не могут быть перехвачены.
app.on('error', (err, ctx) => {
// do something
});
Стоит отметить, что мы можем активно инициировать это событие ошибки внутри фреймворка, и даже если мы поймали и обработали ошибки, мы можем продолжать выбрасывать их на уровень фреймворка, что удобно для многих унифицированных обработок.
ctx.app.emit('error', err, ctx);
Сводка типов ошибок
-
Синхронная ошибка => может быть обнаружена с помощью 1.try...catch 2.window.onerror 3.process.on('uncaughtException').
-
Асинхронные ошибки => setInterval, например, не ждать асинхронных функций и т. д., try ... catch не будет захвачен, и это будет захват window.onerror process.on ('uncaughtException').
Примечание. Ошибка, которая локально перехвачена с помощью try...catch, больше не будет выбрасываться на верхний уровень, поэтому захват глобальной обработки точно не будет перехвачен, если только обработка не будет завершена после завершения перехвата, ошибка будут по-прежнему выбрасываться на верхний слой.
Унифицированная обработка исключений
Общая идея: после того, как бизнес-уровень захватывает и упаковывает ошибку, она продолжает передаваться на верхний уровень. При упаковывании все ошибки наследуются от нашего собственного определенного класса ошибок. В классе ошибок есть много настраиваемых типов ошибок. просто генерируйте экземпляр этого типа ошибки при его генерировании.В финальном промежуточном программном обеспечении мы можем перехватывать все ошибки для унифицированной обработки. На данный момент ошибки классифицированы, засекречены, а некоторые, возможно, никогда раньше не ловились, и тут можно много чего сделать.
определить класс ошибки
class SystemError extends Error {
constructor(message) {
super(message);
// 错误类型
// 错误等级
// 错误信息
// ...
}
static wrapper(e) {
const error = new this(e.message);
// 将e上的各种东西包装到error上
return error;
}
}
//可以对常见的错误提前定义好
createDBError(xxx) {
const sysError = SystemError.wrapper(error);
// 写入错误信息
// 写入错误类型
// 写入错误等级
// ...
return sysError;
}
//这样在业务中抛错的时候只需要简单的
throw createDBError(error, { someInfo });
перехват ошибок
Максимально точно ловите ошибки в бизнесе, выполняйте градацию, классификацию и другие операции в соответствии с ошибками, а затем продолжайте выбрасывать их на верхний уровень.
Поскольку для точного захвата ошибок легко вызвать большое количество вложенных ситуаций try...catch, мы должны максимально избегать такого раздутого кода.
try {
try {
// 操作数据库
} catch (err) {
throw createDBError(error, { someInfo });
}
try {
// 正常业务
} catch (err) {
throw createBusinessError(error, { someInfo });
}
} catch (err) {
throw err
}
В это время должна быть проблема с нашим кодом.В это время мы должны подумать о том, можно ли его разделить, чтобы он не вызывал такой раздутой ситуации.
Унифицированная обработка промежуточного ПО
Поскольку мы только упаковываем все предыдущие ошибки и продолжаем сообщать о них, поэтому в промежуточном программном обеспечении верхнего уровня мы можем обрабатывать все ошибки единообразно.
- Все ошибки, которые мы оборачиваем, происходят из наших пользовательских классов, и мы можем легко определить, какие ошибки нам известны, а какие никогда не обнаруживаются.
- Он может отвечать на запросы и отображать более удобные страницы в зависимости от типа ошибки.
- В зависимости от уровня ошибки можно определить, какие ошибки нужно только собрать, а о каких ошибках нужно сообщить.
- ...
Суммировать
Я некоторое время имел дело с различными ошибками и делился своими достижениями, я надеюсь, что каждый может быть более удобным при работе с исключениями в будущем.