Правильная регистрация ошибок JavaScript в консоли с помощью разборных трассировок стека - PullRequest
0 голосов
/ 11 мая 2018

Я в основном из Java-фона (и, следовательно, из-за мышления Java), поэтому я не уверен, что я здесь что-то понимаю.

Я пытаюсь найти правильный способ входа в систему.ошибка (генерируется где-то выше в стеке, перехваченная через общий низкоуровневый блок catch позже) в веб-консоли браузера при отображении правильной информации трассировки стека приятным разборным способом.Ниже приведен пример веб-клиента Slack Chat , работающего в Firefox:

Slack's error messages, with nice, collapsible stacktraces!

Как видите, по умолчаниюотображается только сообщение об ошибке (первый журнал) со спереди складной стрелкой, которая при щелчке раскрывает полную трассировку стека (второй журнал).Довольно аккуратно, я бы сказал.

Вот что я пробовал:

Создание ошибки внутри вызова вложенной функции:

h = () => TypeError("b");
g = () => h();
f = () => g();
e = f();

Получившийся объект ошибки теперь сохраняется в e.

e, когда передается в console.error(), он показывает свернутую трассировку стека, но, очевидно, он отражает местоположение вызова самой console.error() (трассировкиимеет только одну <anonymous> debugger eval code строку), в дополнение к неразборной копии правильной трассировки стека (содержащей функции f, g и h):

Свернутый (по умолчанию) вид, который по-прежнему показывает (правильную) трассировку стека:

'console.error(e)' collapsed; see the ugly stacktrace that doesn't collapse?

Расширенный вид с отображениемдве трассировки стека (теперь расширенная «неправильная» трассировка стека внизу):

same thing, with the 'collapse' expanded; now we see two stacktraces (including the 'fake' one that had been collapsed earlier)

В качестве альтернативы, если я что-то сделаюкак:

h = () => {
    throw TypeError("b");
}
g = () => h();
f = () => g();
e = f();

Я просто получаю однострочник без трассировки стека:

uncaught throw, no stacktrace in Firefox

(Примечание:Хром вроде быздесь по-другому, выдавая что-то похожее на console.error(e);в этом случае обе трассировки стека являются правильными, но все же есть две трассы, одна из которых неразборная.)

Если я сделаю console.error() только с использованием текста сообщения, на месте (именно там, где должна возникать ошибка):

h = () => {
    console.error("b");
}
g = () => h();
f = () => g();
e = f();

Я вижу ожидаемое поведение:

'console.error()' in-place, with the collapsible stacktrace expanded; just like Slack

ОднакоОчевидно, что это нереальное решение, потому что мне нужно зарегистрировать произвольную ошибку (генерируемую где-то выше в стеке) на более низком уровне (скажем, главный блок catch в исходной функции драйвера).

h = () => {
    throw TypeError("b");
}
g = () => h();
f = () => g();

try {
    e = f();
} catch (e) {
    // expecting to see an error log, with one nice, collapsible stacktrace
    console.error(e);
}

Один из моих коллег предположил, что правильным способом сделать это может быть переопределение функции console.error() по умолчанию с моей собственной пользовательской реализацией, и именно так Slack также может творить чудеса.Это единственный обходной путь или есть более «стандартизированное» (и кросс-браузерное) решение, которое я могу использовать «из коробки» (желательно без использования внешних библиотек)?

1 Ответ

0 голосов
/ 11 мая 2018

(Примечание: Chrome и Firefox обрабатывают это по-разному).

Вы ловите ошибку на верхнем уровне и обрабатываете ее там.В Firefox вы видите стек, но он не разрушается.

Концептуально, он работает следующим образом.Представьте, что карат - это движение ошибки.

^    excution > 
^     function > 
^      function > 
^       function > error thrown (no handling) // shows stack.

^    excution  (handling) > 
     function > 
      function > 
       function > error thrown // does not show stack (in Chrome), because you're handling up here, 

^    excution > 
^     function > 
^      function > 
^       function > error thrown, caught. Catch uses console.error // shows stack because the error is at a different layer in the stack

Теперь посмотрите на отредактированную версию вашего примера, где обработка ниже.

h = () => {
     try {
        throw TypeError("b");
    } catch (e) {
         // expecting to see an error log, with one nice, collapsible stacktrace
         console.error(e);
    }
}
g = () => h();
f = () => g();

f();

Этот код отображает стек.

Ваша «ловля» ошибки на том уровне, на котором вы хотите ее обработать.Смысл его углубления в вызовы заключается в том, чтобы вы могли обработать ошибку, влияющую на код, вызвавший функцию throw, так, как вы этого хотели.

...