В любом случае, до тех пор, пока обновление не может воспроизводить после ошибки JavaScript, пользователь может решить проблему, обновляясь, и браузер не будет терпеть неудачу, и все будет хорошо, если этого не произойдет. Это предположение было правдой до того, как приложение для одной страницы стало популярным. Текущее приложение для одной страницы очень сложное после работы в течение некоторого периода времени. Разве вы не полностью переработали предыдущие операции? Таким образом, нам все еще необходимо захватить и проанализировать эту информацию об исключении, а затем мы можем изменить код, чтобы не влиять на пользовательский опыт.
Как поймать исключения Мы написали сами throw new Error()
которую мы, безусловно, можем захватить, если хотим захватить, потому что мы очень хорошо знаем, где написан throw
. Тем не менее, исключения, которые возникают при вызове API браузера, не обязательно так легко поймать. Для первого мы также можем поймать его через try-catch
, для последнего мы должны выслушать глобальные исключения, а затем поймать его.
Если известно, что некоторые API-интерфейсы браузеров бросают исключения, нам нужно привести к try-catch
чтобы избежать всей программы, входящей в нелегальное состояние из-за ошибок. Например, window.localStorage
- это такой API.
try {
localstorage.setitem ('date', date.now ());
} catch (error) {
ReporterRor (ошибка);
}
Другим try-catch
применимым сценарием является обратный сценарий. Поскольку код функции обратного вызова неконтролируемого, мы не знаем, насколько хорош этот код и будут ли называться другие API, которые бросают исключения. Чтобы не привести к выполнению других кодов после вызова обратного вызова из-за ошибок обратного вызова, необходимо вернуть вызов обратно в try-catch
.
listeners.forEach(function(listener) {
пытаться {
слушатель ();
} catch (error) {
ReporterRor (ошибка);
}
});
Для мест, которые try-catch
, не может покрыть, если происходит исключение, его можно поймать только через window.onerror
.
window.onerror =
function (errormessage, scripturi, lineNumber) {
ReporterRor ({
Сообщение: Errormessage,
Скрипт: Scripturi,
Линия: белье
});
}
Будьте осторожны, чтобы не быть умным и использовать window.addEventListener
или window.attachEvent
, чтобы прослушать window.onerror
. Многие браузеры реализуют только window.onerror
или только window.onerror
реализация является стандартной. Учитывая, что стандартный черновик также определяет window.onerror
, нам просто нужно использовать window.onerror
.
Предположим, что у нас есть функция reportError
для сбора пойманных исключений, а затем отправить их в хранилище на стороне сервера партиями для запроса и анализа, какую информацию мы хотим собрать? Более полезная информация включает в себя: Тип ошибки ( name
), сообщение об ошибке ( message
), адрес файла скрипта ( script
), номер строки ( line
), номер столбца ( column
) и Stack Trace ( stack
). Если исключение попадает через try-catch
, вся эта информация находится на объекте Error
(поддерживается основными браузерами), поэтому reportError
также может собирать эту информацию. Но если он захвачен через window.onerror
, мы все знаем, что эта функция события имеет только 3 параметра, поэтому неожиданная информация об этих 3 параметрах теряется.
Если объект Error
создается нами, то error.message
контролируется нами. По сути, то, что мы вкладываем в error.message
, какой будет первый параметр ( message
) window.onerror
. (Браузер на самом деле сделает немного изменен, например, добавление 'Uncaught Error: '
JSON.Stringify
error.message
их в window.onerror
Конечно, это ограничивается объектами Error
, которые мы создаем сами.
Производители браузеров также знают ограничения, которые люди подвергаются при использовании window.onerror
, поэтому они начинают добавлять новые параметры в window.onerror
. Учитывая, что только номера строк и никакие номера столбцов кажутся очень симметричными, т.е. сначала добавили номера столбцов и поместили их в четвертый параметр. Тем не менее, все больше обеспокоены тем, могут ли они получить полный стек, поэтому Firefox сказал, что было бы лучше поставить стек в пятый параметр. Но Chrome сказал, что было бы лучше поместить весь объект Error
в пятый параметр, и вы можете прочитать любые атрибуты, включая пользовательские атрибуты. В результате Chrome движется быстрее, новое window.onerror
Подпись Onerror в Chrome 30, что приводит к следующему написанию стандартного проекта.
Регулярность атрибутовwindow.onerror = function(
errormessage,
Scripturi,
бегство,
столбцы,
ошибка
) {
if (ошибка) {
ReporterRor (ошибка);
} еще {
ReporterRor ({
Сообщение: Errormessage,
Скрипт: Scripturi,
Линия: льняное число,
Столбец: ColumnNumber
});
}
}
Имена script
filename
Error
, которые мы уже обсуждали, основаны на методах именования Error
. Поэтому нам также нужна специальная функция, чтобы нормализовать объект Error
, то есть отобразить разные имена атрибутов с единым именем атрибута. Для конкретных практик, пожалуйста, обратитесь к этой статье. Хотя реализация браузера будет обновлена, людям не будет слишком сложно поддерживать такую таблицу отображения.
Аналогичный формат stack
трассировки. Это свойство сохраняет информацию о стеке исключения, когда оно происходит в виде простого текста. Имя ( identifier
), файл ( script
), номер строки ( line
) и номер столбца ( column
).
Если вы также столкнулись с ошибкой с сообщением 'Script error.'
Причина этого ограничения безопасности заключается в следующем: Предположим, что HTML, возвращенный онлайн-банкиром после входа в систему, отличается от HTML, которого можно увидеть анонимным пользователем, сторонний веб-сайт может поместить URI этого онлайн-банка в script.src
атрибут script.src
. Конечно, HTML не может быть проанализирован как JS, поэтому браузер вызовет исключение, и этот сторонний веб-сайт может определить, вошел ли пользователь, анализируя местоположение исключения. По этой причине браузер фильтровали все исключения, брошенные различными файлами сценариев исходной, оставляя только неизменное сообщение, как 'Script error.'
И все другие атрибуты исчезают.
Для веб -сайтов определенного масштаба это нормально для размещения файлов сценариев на CDN и различных источников. Теперь, даже если вы создаете небольшой веб -сайт самостоятельно, общие фреймворки, такие как JQUERY и BACKBONE, могут напрямую ссылаться на версию на публичном CDN, чтобы ускорить загрузки пользователей. Таким образом, это ограничение безопасности вызывает некоторые проблемы, что приводит к тому, что информация о исключении, которую мы собираем от Chrome и Firefox, быть бесполезной 'Script error.'
.
Если вы хотите обойти это ограничение, просто убедитесь, что файл сценария и сами страница одинаковы. Но разве не размещение файлов сценариев на серверах, которые не ускоряются CDN, уменьшить скорость загрузки пользователя? Одним из решений является продолжение размещения файла скрипта на CDN, используйте XMLHttpRequest
, чтобы загрузить контент обратно через Cors, а затем создать тег <script>
для внедрения его в страницу. Код, встроенный на странице, конечно, является тем же происхождением.
Это просто сказать, но есть много деталей для реализации. Чтобы привести простой пример:
<script src="http://cdn.com/step1.js"></script>
<Скрипт>
(функция step2 () {}) ();
</script>
<script src = "http://cdn.com/step3.js"> </script>
Мы все знаем, что если в шаге 1, шаге 2 и шаге 3 зависимости он должен выполняться строго в этом порядке, в противном случае может возникнуть ошибка. Браузер может запросить файлы STEP1 и STEP3 параллельно, но заказ гарантирован при выполнении. Если мы получим содержимое файла Step1 и Step3, используя XMLHttpRequest
, мы должны обеспечить правильный порядок нашего собственного. Кроме того, не забывайте шаг2.
Если у нас уже есть полный набор инструментов для генерации тегов <script>
для разных страниц на веб -сайте, нам нужно настроить этот набор инструментов для внесения изменений в теги <script>
:
<script>
phoneulerEmotescript ('http://cdn.com/step1.js');
</script>
<Скрипт>
ganedicinlinescript (function code () {
(функция step2 () {}) ();
});
</script>
<Скрипт>
phoneulerEmotescript ('http://cdn.com/step3.js');
</script>
Нам необходимо реализовать две функции scheduleRemoteScript
и scheduleInlineScript
, и убедиться, что они определены до первого тега <script>
, который ссылается на внешний файл сценария, а затем оставшиеся теги <script>
будут переписаны в вышеупомянутую форму. Обратите внимание, что функция step2
, которая была выполнена немедленно, была помещена в более крупную функцию code
. Функция code
не будет выполнена, это просто контейнер, так что исходный код STEP2 можно сохранить без выхода, но он не будет выполнен немедленно.
Затем нам необходимо реализовать полный механизм, чтобы гарантировать, что содержимое файла, загруженное с помощью scheduleRemoteScript
на основе адреса, и кода, непосредственно полученный с помощью scheduleInlineScript
может быть выполнен один за другим в правильном порядке. Я не дам подробный код здесь.
Получение контента через COR и инъекционное код на страницу может преодолеть ограничения безопасности, но это введет новую проблему, то есть конфликты номера строк. Первоначально уникальный файл скрипта может быть расположен через error.script
, а затем уникальный номер строки может быть расположен через error.line
. Теперь, поскольку все это <script>
, встроенные на странице, несколько тегов <script>
нельзя различить по error.script
. ..
Чтобы избежать конфликтов номера строки, мы можем тратить некоторые номера строк, чтобы интервалы номера строки, используемые фактическим кодом в каждом теге <script>
, не перекрывались друг с другом. Например, предполагая, что фактический код в каждом теге <script>
не превышает 1000 строк, тогда я могу позволить коду в первой тег <script>
Line 11000 и позвольте второму <script>
Tag в коде кода Занимает строку 10012000 (1000 пустая линия, вставленная перед вставкой), код третьего тега <script>
занимает строку 20013000 (2000 пустая линия, вставленная перед вставкой) и так далее. Затем мы используем атрибут data-*
для записи этой информации для легкой проверки.
<script
data-src = "http://cdn.com/step1.js"
data-line-start = "1"
>
// код для шага 1
</script>
<script data-line-start = "1001">
// '/n' * 1000
// код для шага 2
</script>
<Скрипт
data-src = "http://cdn.com/step3.js"
data-line-start = "2001"
>
// '/n' * 2000
// код для шага 3
</script>
После этой обработки, если ошибка ошибки error.line
составляет 3005
, это означает, что фактической error.script
должна быть 'http://cdn.com/step3.js'
, в то время как фактическая error.line
должна быть 5
. Мы можем завершить этот номер строки обратной проверки в функции reportError
, упомянутой ранее.
Конечно, поскольку мы не можем гарантировать, что каждый файл сценария имеет только 1000 строк, также возможно, что некоторые файлы сценария составляют значительно менее 1000 строк, поэтому нет необходимости приспособленно выделять 1000 строк по каждому тегу <script>
. Мы можем выделить интервалы на основе фактического количества линий сценариев, просто убедитесь, что интервалы, используемые каждым тегом <script>
, не перекрываются.
Ограничения безопасности, налагаемые браузерами на содержание из разных источников, конечно, не ограничиваются тегом <script>
. Поскольку XMLHttpRequest
может прорваться через это ограничение через Cors, почему ресурсы непосредственно ссылаются через теги не разрешены? Это, безусловно, нормально.
Ограничение ссылки на различные файлы скриптов источника для тегов <script>
также применяется к ссылке на различные файлы изображений источника для тегов <img>
. Если тег <img>
является другим источником, как только он используется при рисовании <canvas>
, <canvas>
станет состоянием только для записи, гарантируя, что веб-сайт не может украсть несанкционированные данные изображения из разных источников через JavaScript. Позже, тег <img>
решил эту проблему, введя атрибут crossorigin
. Если используется crossorigin="anonymous"
, он эквивалентен анонимным Cors;
Поскольку тег <img>
может сделать это, почему тег <script>
не может сделать это? Следовательно, производитель браузеров добавил тот же атрибут crossorigin
к тегу <script>
для решения вышеуказанных ограничений безопасности. Теперь поддержка Chrome и Firefox для этой собственности полностью бесплатная. Safari будет относиться к crossorigin="anonymous"
как crossorigin="use-credentials"
, и результатом является то, что если сервер поддерживает только анонимные Cors, Safari будет рассматривать аутентификацию как сбой. Поскольку сервер CDN предназначен для возврата только статического контента по соображениям производительности, невозможно динамически вернуть заголовок HTTP, необходимый для аутентификации COR на основе запросов.
Обработка исключений JavaScript выглядит просто и ничем не отличается от других языков, но не так легко поймать все исключения и проанализировать свойства. Хотя некоторые сторонние услуги теперь предоставляют услуги Google Analytics, которые затрагивают исключения JavaScript, если вы хотите понять детали и принципы, вы должны сделать это самостоятельно.