Почему стек вывода ошибки в асинхронном коде отличается от синхронного
Почему в асинхронном коде в ошибке не выводится полный стек вызовов?

Чтобы прояснить, давайте разберем на таком примере :
import fs from 'fs';
const func1 = () => {
const func2 = () => {
callUndefinedFunction();
};
fs.readFile('./directory', 'utf-8', func2);
};
func1();
Вывод ошибки будет таким:
file:///tmp/test1/index.js:5
callUndefinedFunction();
^
ReferenceError: callUndefinedFunction is not defined
at ReadFileContext.func2 [as callback] (file:///tmp/test1/index.js:5:5)
at FSReqCallback.readFileAfterOpen [as oncomplete] (node:fs:314:13)
Стек ошибки показывает на функцию func2()
, но в нём нет родительской функции func1()
вот эта строка:
at ReadFileContext.func2 [as callback] (file:///tmp/test1/index.js:5:5)
Дальше стек ошибки указывает на место в библиотечном коде: node:fs:314:13
- это мы уже не смотрим.
Теперь рассмотрим такой пример, уже с синхронным кодом:
const func2 = () => {
throw Error();
};
const func1 = () => {
func2();
};
func1();
Тут просто одна функция вложена в другую. Стек ошибки этого кода будет таким:
file:///tmp/test1/index-1.js:3
throw Error();
^
Error
at func2 (file:///tmp/test1/index-1.js:3:11)
at func1 (file:///tmp/test1/index-1.js:6:3)
at file:///tmp/test1/index-1.js:9:1
at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
В стеке уже указываются обе функции, первые две строки:
at func2 (file:///tmp/test1/index-1.js:3:11)
at func1 (file:///tmp/test1/index-1.js:6:3)
Дальше идут строки из внутреннего кода ноды. По этому выводу мы видим стек ошибки, где на верхнем уровне стека функция func2()
, внутри которой и была ошибка, ниже идёт func1()
, внутри которой была вызвана функция func2()
. То есть в стеке обе наши функции. В первом же примере в стеке нет функции func1()
, там сразу на первом уровне стека идёт ReadFileContext.func2 (это по сути и есть наша функция-колбек func2()
). Метод fs.readFile()
вызвался, создал новый стек и поместил в этот стек колбек. Именно поэтому в нём нет func1()
.