что является исключением
Это означает, что пользователь не может получить ожидаемый результат при использовании приложения. Различные аномалии имеют разную степень последствий, начиная от неприятных пользователей и заканчивая непригодными для использования продуктами в тяжелых случаях, что приводит к тому, что пользователи теряют признание продукта.
Зачем обрабатывать исключения
- Улучшить пользовательский опыт
- проблема удаленного местоположения
- Проблема не воспроизводится, особенно на мобильном терминале, по разным причинам, это может быть версия системы, модель и т.д.
Каковы исключения в интерфейсе
| аномальный | частота |
|---|---|
| Исключения JavaScript (синтаксические ошибки, ошибки кода) | часто |
| Исключение загрузки статических ресурсов (img, js, css) | Иногда |
| Исключение запроса Ajax | Иногда |
| обещать исключение | меньше |
| исключение iframe | меньше |
Как ловить исключения
try-catch
try-catchМогут быть перехвачены только синхронные ошибки времени выполнения, но не перехвачены синтаксические и асинхронные ошибки.
1. Ошибка синхронизации
try {
kill;
} catch(err) {
console.error('try: ', err);
}
результат:try: ReferenceError: kill is not defined
2. Невозможно отловить синтаксические ошибки
try {
let name = '1;
} catch(err) {
console.error('try: ', err);
}
результат:Unterminated string constant
Компилятор может предотвратить запуск синтаксических ошибок.
3. Невозможно отловить асинхронные ошибки
try {
setTimeout(() => {
undefined.map(v => v);
}, 1000);
} catch(err) {
console.error('try: ', err);
}
результат:Uncaught TypeError: Cannot read property 'map' of undefined
window.onerror
когдаJavaScriptКогда возникают ошибки времени выполнения (включая синтаксические ошибки),windowвызоветErrorEventинтерфейсerrorсобытие и выполнитьwindow.onerror()Если функция возвращаетtrue, выполнение обработчика событий по умолчанию запрещено.
1. Ошибка синхронизации
/**
* @param {String} message 错误信息
* @param {String} source 出错文件
* @param {Number} lineno 行号
* @param {Number} colno 列号
* @param {Object} error error对象
*/
window.onerror = (message, source, lineno, colno, error) => {
console.error('捕获异常:', message, source, lineno, colno, error);
return true;
};
kill;
Результат: исключение захвата:Uncaught ReferenceError: kill is not defined
2. Невозможно отловить синтаксические ошибки
/**
* @param {String} message 错误信息
* @param {String} source 出错文件
* @param {Number} lineno 行号
* @param {Number} colno 列号
* @param {Object} error error对象
*/
window.onerror = (message, source, lineno, colno, error) => {
console.error('捕获异常:', message, source, lineno, colno, error);
return true;
};
let name = '1;
результат:Unterminated string constant
Компилятор может предотвратить запуск синтаксических ошибок.
3. Асинхронная ошибка
/**
* @param {String} message 错误信息
* @param {String} source 出错文件
* @param {Number} lineno 行号
* @param {Number} colno 列号
* @param {Object} error error对象
*/
window.onerror = (message, source, lineno, colno, error) => {
console.error('捕获异常:', message, source, lineno, colno, error);
return true;
};
setTimeout(() => {
undefined.map(v => v);
}, 1000);
результат:捕获异常: Uncaught TypeError: Cannot read property 'map' of undefined`
window.addEventListener('error')
Когда ресурс (например,<img>или<script>) не удалось загрузить, элемент, который загружает ресурс, вызоветEventинтерфейсerrorсобытие и выполнитьonerror()функция обработчика. ЭтиerrorСобытия не всплываютwindow, но (по крайней мере, в Firefox) может использоваться однимwindow.addEventListenerзахватывать.
<script>
window.addEventListener('error', (err) => {
console.error('捕获异常:', err);
}, true);
</script>
<img src="./test.jpg" />
результат:捕获异常:Event {isTrusted: true, type: "error", target: img, currentTarget: Window, eventPhase: 1, …}
window.addEventListener('unhandledrejection')
когдаPromiseодеялоrejectи нетrejectКогда процессор, он сработаетunhandledrejectionсобытие; это может произойти вwindowвниз, но может возникать и вWorkerсередина. Это полезно для отладки резервной обработки ошибок.
window.addEventListener("unhandledrejection", (err) => {
err.preventDefault();
console.error('捕获异常:', err);
});
Promise.reject('promise');
результат:捕获异常:PromiseRejectionEvent {isTrusted: true, promise: Promise, reason: "promise", type: "unhandledrejection", target: Window, …}
Vue
Vue.config.errorHandler = (err, vm, info) => {
console.error('捕获异常:', err, vm, info);
}
React
React16, который предоставляет встроенную функциюcomponentDidCatch, используя его, можно очень просто получитьReactсообщение об ошибке ниже.
componentDidCatch(error, info) {
console.error('捕获异常:', error, info);
}
Тем не менее, рекомендуетсяErrorBoundary
в пользовательском интерфейсеJavaScriptОшибки не должны нарушать работу всего приложения. чтобыReactпользователи решают эту проблему,React16Вводится новое понятие «границы ошибки».
новыйErrorBoundary.jsxКомпоненты:
import React from 'react';
import { Result, Button } from 'antd';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, info: '' };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
this.setState({
info: error + ''
});
}
render() {
if (this.state.hasError) {
// 你可以渲染任何自定义的降级 UI
return (
<Result
status="500"
title="500"
subTitle={this.state.info}
extra={<Button type="primary">Report feedback</Button>}
/>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
использовать:
<ErrorBoundary>
<App />
</ErrorBoundary>
Уведомление
Граничная ошибка не фиксирует ошибки в следующих областях:
- обработчик события
- Асинхронный код (например,
setTimeoutилиrequestAnimationFrameПерезвоните) - Рендеринг на стороне сервера
- Ошибки, возникающие в самой границе ошибки (а не в ее дочерних элементах)
iframe
Из-за «Политики того же происхождения», установленной браузером, она не может быть обработана очень изящно.iframeИсключение, помимо основных свойств, таких как его ширина и высота, не может быть получено изiframeПолучите много информации.
<script>
document.getElementById("myiframe").onload = () => {
const self = document.getElementById('myiframe');
try {
(self.contentWindow || self.contentDocument).location.href;
} catch(err) {
console.log('捕获异常:' + err);
}
};
</script>
<iframe id="myiframe" src="https://nibuzhidao.com" frameBorder="0" />
Sentry
Очень отличный продукт в индустрии для мониторинга исключений, автор тоже использует этот продукт, и документация полная.
Какую информацию необходимо сообщить
- неправильный идентификатор
- ID пользователя
- имя пользователя
- IP-адрес пользователя
- оборудование
- сообщение об ошибке
- браузер
- версия системы
- Версия приложения
- модель
- отметка времени
- Уровень исключения (ошибка, предупреждение, информация)
отчет об исключении
1. Ajax отправляет данные
2. Динамически создавать теги img
Если количество аномальных данных велико, что приводит к высокой нагрузке на сервер, отрегулируйте частоту отправки (вы можете рассмотреть возможность хранения аномальной информации на клиенте, установить порог времени и сообщить об этом) или установить скорость сбора (скорость сбора должна быть установлен в соответствии с реальной ситуацией, случайным числом или некоторыми характеристиками пользователя.