El seguimiento de la pila es un método estable para identificar el error que se produce en el programa cuando se llama a la función de ese programa. Ayuda a los programadores a verificar de dónde viene el error/excepción en particular y cuál es la razón detrás de él. Dependiendo de la hora en que se recopilan los datos de seguimiento, el tamaño del archivo para estos seguimientos puede ser enorme. Tenemos que encontrar una manera de obtener un seguimiento de la pila de JavaScript al generar un error/excepción.
El seguimiento de la pila es un informe de los marcos de pila activos en un momento determinado durante la ejecución de un programa. Cuando el programa se está ejecutando, la memoria a menudo se asigna dinámicamente en la pila y en el montón. La pila es más activa en comparación con el montón porque generalmente es una región continua de memoria que asigna contexto local para cada función en ejecución. Stack también se refiere a la construcción de programación, por lo que esta pila se denomina pila de tiempo de ejecución de un programa. Una vez que se ha asignado un bloque de memoria en la pila. No se puede eliminar fácilmente, ya que puede haber otros bloques de memoria que se asignaron antes. Cada vez que se llama a la función en el programa, se asigna un bloque de memoria en la parte superior de la pila de tiempo de ejecución llamado registro de activación. Los programadores suelen utilizar el seguimiento de pila durante la interacción y la depuración.
Stack es un tipo de estructura de datos donde los datos se pueden almacenar en forma de último en entrar, primero en salir (LIFO) . Significa que la pila es un tipo de almacenamiento y cuando un grupo de datos entra dentro de la pila, se almacena uno por uno de tal manera que los últimos datos se eliminan primero y los primeros datos se eliminan al final. La forma en que cualquier grupo de almacén de datos y eliminación de la pila se puede entender mediante el seguimiento de la pila.
Existen los siguientes métodos mediante los cuales podemos obtener un seguimiento de pila para JavaScript al lanzar una excepción.
Uso de console.trace: el objeto de la consola también tiene un método llamado método console.trace() , que le brinda el seguimiento en la consola. Cada vez que se llama, se genera un seguimiento de pila para la función. Podemos entender esto con la ayuda de este ejemplo.
- Programa:
// Sum function
function
sum(a, b) {
console.trace(
'sum called with '
, a,
'and'
, b);
return
a+b;
}
// Calculation function
function
calc() {
return
sum(8, 11) + sum(9, 14);
}
// Start function
function
start() {
var
a = sum(2, 3);
var
b = calc();
}
// Calling start function
start();
- Producción:
/usr/bin/node stacktrace.js Trace: add called with 2 and 3 at sum (/home/dev/Documents/stacktrace.js:2:13) at start (/home/dev/Documents/stacktrace.js:11:13) at Object. (/home/dev/Documents/stacktrace.js:16:1) at Module._compile (internal/modules/cjs/loader.js:959:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10) at Module.load (internal/modules/cjs/loader.js:815:32) at Function.Module._load (internal/modules/cjs/loader.js:727:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10) at internal/main/run_main_module.js:17:11 Trace: add called with 8 and 11 at sum (/home/dev/Documents/stacktrace.js:2:13) at calc (/home/dev/Documents/stacktrace.js:7:12) at start (/home/dev/Documents/stacktrace.js:12:13) at Object. (/home/dev/Documents/stacktrace.js:16:1) at Module._compile (internal/modules/cjs/loader.js:959:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10) at Module.load (internal/modules/cjs/loader.js:815:32) at Function.Module._load (internal/modules/cjs/loader.js:727:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10) at internal/main/run_main_module.js:17:11 Trace: add called with 9 and 14 at sum (/home/dev/Documents/stacktrace.js:2:13) at calc (/home/dev/Documents/stacktrace.js:7:25) at start (/home/dev/Documents/stacktrace.js:12:13) at Object. (/home/dev/Documents/stacktrace.js:16:1) at Module._compile (internal/modules/cjs/loader.js:959:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10) at Module.load (internal/modules/cjs/loader.js:815:32) at Function.Module._load (internal/modules/cjs/loader.js:727:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10) at internal/main/run_main_module.js:17:11
Usando el objeto de error: podemos crear un objeto de error y devolver el atributo de pila . Una propiedad de pila no estándar del objeto Error le brinda el seguimiento de la pila cuando se llamó a esa función en particular desde qué línea y archivo, y con qué argumentos. La string de la pila procede de las llamadas más recientes a las anteriores.
// Sum function function sum(a, b) { console.log( new Error().stack); return a+b; } // Calculation function function calc() { return sum(8, 11) + sum(9, 14); } // Start function function start() { var a = sum(2, 3); var b = calc(); } // Calling start function start(); |
/usr/bin/node trace.js Error at sum (/home/dev/Documents/trace.js:2:17) at start (/home/dev/Documents/trace.js:11:13) at Object. (/home/dev/Documents/trace.js:16:1) at Module._compile (internal/modules/cjs/loader.js:959:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10) at Module.load (internal/modules/cjs/loader.js:815:32) at Function.Module._load (internal/modules/cjs/loader.js:727:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10) at internal/main/run_main_module.js:17:11 Error at sum (/home/dev/Documents/trace.js:2:17) at calc (/home/dev/Documents/trace.js:7:12) at start (/home/dev/Documents/trace.js:12:13) at Object. (/home/dev/Documents/trace.js:16:1) at Module._compile (internal/modules/cjs/loader.js:959:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10) at Module.load (internal/modules/cjs/loader.js:815:32) at Function.Module._load (internal/modules/cjs/loader.js:727:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10) at internal/main/run_main_module.js:17:11 Error at sum (/home/dev/Documents/trace.js:2:17) at calc (/home/dev/Documents/trace.js:7:25) at start (/home/dev/Documents/trace.js:12:13) at Object. (/home/dev/Documents/trace.js:16:1) at Module._compile (internal/modules/cjs/loader.js:959:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10) at Module.load (internal/modules/cjs/loader.js:815:32) at Function.Module._load (internal/modules/cjs/loader.js:727:14) at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10) at internal/main/run_main_module.js:17:11
Uso del objeto llamador: hemos implementado una función llamada stacktrace que devolverá una string que representa el historial de llamadas hasta el punto donde se llamó a stacktrace() . Internamente, utiliza otra función llamada st2 que se llamará recursivamente atravesando el árbol de llamadas hasta el punto en el que llegamos al cuerpo principal de nuestro script JavaScript. Al final de la declaración de stacktrace, llamamos a st2 con arguments.callee.caller . arguments es un objeto especial que pertenece a la llamada de función actual y que contiene mucha información sobre la llamada actual. Luego, se llama recursivamente a la función st2 y devuelve la string stacktrace hasta el momento.
- Programa:
// Sum function
function
sum(a,b) {
// Calling stacktrace function
console.log(stacktrace());
return
a+b;
}
// Calculation function
function
calc() {
return
sum(8, 11) + sum(9, 14);
}
// Start function
function
start() {
var
a = sum(2, 3);
var
b = calc();
}
// Calling start function
start();
// Stacktrace function
function
stacktrace() {
function
st2(f) {
var
args = [];
if
(f) {
for
(
var
i = 0; i < f.arguments.length; i++) {
args.push(f.arguments[i]);
}
var
function_name = f.toString().
split(
'('
)[0].substring(9);
return
st2(f.caller) + function_name +
'('
+ args.join(
', '
) +
')'
+
"\n"
;
}
else
{
return
""
;
}
}
return
st2(arguments.callee.caller);
}
- Producción:
/usr/bin/node stackt.js ([object Object], function require(path) { return mod.require(path); }, [object Object], /home/dev/Documents/stackt.js, /home/dev/Documents) start() sum(2, 3) ([object Object], function require(path) { return mod.require(path); }, [object Object], /home/dev/Documents/stackt.js, /home/dev/Documents) start() calc() sum(8, 11) ([object Object], function require(path) { return mod.require(path); }, [object Object], /home/dev/Documents/stackt.js, /home/dev/Documents) start() calc() sum(9, 14)