Hidden gems of the Chrome DevTools, Part 1: The Console API
Juhana Jauhiainen
Posted on April 3, 2021
Debugging, or finding the reason why your code doesn't work, is one of the most important skills a software developer needs. If you can debug effectively, you'll catch problems faster and even gain a better understanding of how things work under the hood.
In frontend development, we have a variety of tools available to debug our code. We can use a debugger to step through our code, we can log values to the browser console and we can use the DevTools of our browser.
This article series focuses on the Chrome DevTools and will go through some of the more unknown or experimental features. These might be features you'll add to your toolbox and use daily or something you might want to check occasionally when improving accessibility or performance.
In the first article of the series, I'll cover some less known methods of the Console API
The Console API
As JavaScript developers, we are familiar with the log
, warn
, and error
methods of the Console API. But the Console API has many more methods that can be used when debugging.
trace()
trace
can be used to print the current stack trace. You've probably seen a stack trace when an error has occurred in your application. Using trace
you can print the current stack trace even if no error has occurred.
An example situation where you might use trace
could be when you're unsure which place in your code is calling a method.
function someFunc() {
console.trace();
return "Hello!";
}
function otherFunc() {
someFunc();
}
setTimeout(someFunc, 0);
otherFunc();
// Trace
// at someFunc (/home/runner/BlandWelllitComments/index.js:2:13)
// at otherFunc (/home/runner/BlandWelllitComments/index.js:6:5)
// at /home/runner/BlandWelllitComments/index.js:9:1
// at Script.runInContext (vm.js:130:18)
// at Object.<anonymous> (/run_dir/interp.js:209:20)
// at Module._compile (internal/modules/cjs/loader.js:999:30)
// at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
// at Module.load (internal/modules/cjs/loader.js:863:32)
// at Function.Module._load (internal/modules/cjs/loader.js:708:14)
// at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
// Trace
// at Timeout.someFunc [as _onTimeout] (/home/runner/BlandWelllitComments/index.js:2:13)
// at listOnTimeout (internal/timers.js:554:17)
// at processTimers (internal/timers.js:497:7)
The actual trace you'll get depends on what kind of environment you run the code in. The trace in the example is actually from repl.it. The console API works mostly the same in Node.js and the browser.
assert([expression, errorMsg])
assert
can be used to print an error message to the console if something unexpected happens. This is useful for example if you're writing a library. assert
takes as parameters an expression and an object. If the expression evaluates as false
- an error is thrown. The object is printed to the console along with the error.
function doSomething(obj) {
console.assert(obj.someProperty, "someProperty needs to be set!")
}
doSomething({});
// Assertion failed: someProperty needs to be set!
❗️ console.assert
only prints the error message to the console. It does not do any error handling for you!
table([data])
table
is a method that prints data as a table which is easier to read than just printing objects. This could be useful when you have lots of data and want to debug it.
const data = [
{
city: "Tokyo",
country: "Japan",
population: 37_977_000
},
{
city: "Jakarta",
country: "Indonesia",
population: 34_540_000
},
{
city: "Delhi",
country: "India",
population: 29_617_000
}
]
console.table(data)
// ┌─────────┬───────────┬─────────────┬────────────┐
// │ (index) │ city │ country │ population │
// ├─────────┼───────────┼─────────────┼────────────┤
// │ 0 │ 'Tokyo' │ 'Japan' │ 37977000 │
// │ 1 │ 'Jakarta' │ 'Indonesia' │ 34540000 │
// │ 2 │ 'Delhi' │ 'India' │ 29617000 │
// └─────────┴───────────┴─────────────┴────────────┘
You can also supply an array of fields to table
, and only those fields will be printed.
console.table(data, ["city", "population"])
// ┌─────────┬───────────┬────────────┐
// │ (index) │ city │ population │
// ├─────────┼───────────┼────────────┤
// │ 0 │ 'Tokyo' │ 37977000 │
// │ 1 │ 'Jakarta' │ 34540000 │
// │ 2 │ 'Delhi' │ 29617000 │
// └─────────┴───────────┴────────────┘
count([label]) and countReset([label])
count
prints the number of times the method has been called on the same line with the same label. This can be useful when you want to find out how many times something is occurring.
for (let i = 0; i < 100; i++) {
const value = Math.random() * 100;
if (value > 10)
console.count("Value is over 10!", value);
}
// ...
// Value is over 10!: 84
// Value is over 10!: 85
// Value is over 10!: 86
// Value is over 10!: 87
// Value is over 10!: 88
// Value is over 10!: 89
// Value is over 10!: 90
If you want to reset the counter at some point, you can use countReset
. You must supply it with the label if you used one with the count
call.
time([label]) and timeEnd([label])
If you're trying to find out what is causing poor performance, your first stop is probably the Chrome DevTools performance tab. Sometimes, however, it's useful to measure the time it takes to run some code in your application. This is where time
and timeEnd
become useful.
console.time("random");
for (let i = 0; i < 10000; i++)
Math.random();
console.timeEnd("random");
//random: 3.029ms
The methods accept a label that makes it possible to have multiple timings going on at the same time. If no label is provided, the label default
is used.
group([title]), groupCollapsed([title]) and groupEnd
If you're logging a lot of things it might be useful to group the console.log
calls so they will be easier to view. This can be done with console.group
.
group
takes the title of the group. The following console.log
calls will be grouped under the title.
console.group("group1")
console.log("Starting random numbers")
for (let i = 0; i < 10; i++)
console.log(Math.random() * 100)
console.groupEnd()
// group1
// Starting random numbers
// 87.92193095845431
// 81.99300123275765
// 84.99678268072954
// 2.290929000620534
// 74.45009215115104
// 36.5278113066769
// 9.250056218875692
// 7.181886970350249
// 29.206363066629937
// 20.1791813157987
The above example shows the console print from Node.js. On the browser, the group will be printed with a handle for opening/closing the group. By default all groups are open, but using the groupCollapsed
method you can print a group that is closed by default.
clear
Finally, with clear
you can clear the console. If you're printing a lot of things, for example in a loop, you might want to have only the latest log
calls visible.
for (let i = 0; i < 100; i++) {
console.clear();
console.log(`Index ${i}`)
}
//Index 99
In the browser, clear
works only if Preserve log
is not enabled in the DevTools settings.
Learn more
Photo by Todd Quackenbush on Unsplash
Posted on April 3, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.