70450aa66d
Tests / frontend-test (push) Successful in 1m25s
Co-authored-by: gorbenko.pavel <gorbenko.pavel@tansu.kz> Reviewed-on: http://git.tnsu.kz/timur.gorodetskiy/request-portal/pulls/5
52 lines
3.0 KiB
TypeScript
52 lines
3.0 KiB
TypeScript
// Читаемый лог необработанных отклонений промисов.
|
||
//
|
||
// Зачем: SPFx вешает на window свой обработчик unhandledrejection, и в консоль
|
||
// попадает только его собственный стек внутри минифицированного бандла —
|
||
// примерно такой:
|
||
//
|
||
// Error
|
||
// at vp (...request-portal-web-part_<hash>.js:9:397946)
|
||
// at t.onUnhandledRejection (...)
|
||
//
|
||
// Ни причины, ни места, где промис отклонился, там нет: SPFx логирует САМ факт,
|
||
// а не `reason`. Поэтому вешаем свой слушатель — он срабатывает наравне с
|
||
// SPFx-овским и печатает то, что действительно нужно: сообщение, стек и сам
|
||
// объект причины (у ошибок PnPjs/SharePoint внутри лежит ответ сервера).
|
||
//
|
||
// Ничего не подавляем (preventDefault не зовём) — поведение портала не
|
||
// меняется, добавляется только диагностика.
|
||
|
||
const PREFIX = '[Портал заявок]';
|
||
|
||
// Слушатель вешается один раз на страницу: на странице может быть несколько
|
||
// экземпляров веб-части, и каждый вызвал бы install() в onInit — без флага
|
||
// одна и та же ошибка печаталась бы столько раз, сколько их размещено.
|
||
let installed = false;
|
||
|
||
// Причиной отклонения может быть что угодно, не только Error — у PnPjs это
|
||
// бывает объект с полями ответа. Разбираем по факту, а не по ожиданию.
|
||
function describeReason(reason: unknown): string {
|
||
if (reason instanceof Error) return `${reason.name}: ${reason.message}`;
|
||
if (typeof reason === 'string') return reason;
|
||
try {
|
||
return JSON.stringify(reason);
|
||
} catch {
|
||
// Циклические ссылки — тогда хотя бы тип.
|
||
return Object.prototype.toString.call(reason);
|
||
}
|
||
}
|
||
|
||
export function installErrorLogging(): void {
|
||
if (installed) return;
|
||
installed = true;
|
||
|
||
window.addEventListener('unhandledrejection', (e: PromiseRejectionEvent) => {
|
||
const reason: unknown = e.reason;
|
||
console.error(`${PREFIX} Необработанная ошибка: ${describeReason(reason)}`);
|
||
// Стек и объект — отдельными аргументами: так консоль браузера даёт
|
||
// раскрыть объект и перейти по стеку, а не показывает «[object Object]».
|
||
if (reason instanceof Error && reason.stack) console.error(`${PREFIX} Стек:`, reason.stack);
|
||
console.error(`${PREFIX} Причина целиком:`, reason);
|
||
});
|
||
}
|