Debugging: The Basics

Writing code is an iterative process: write code, break code, debug code, rewrite code and leave it for the next developer to figure out. Most developers spend more time debugging code than actually writing it. Thus, we believe that you should become intimately familiar with built-in browser developer tools to save you time.

Note: This tutorial will only explain debugging concepts that are most relevant to the ChartIQ library.

See Troubleshooting and FAQ for examples of common debugging issues.

JavaScript is an Asynchronous Language!

The most common mistakes we see have to do with JavaScript's asynchronous nature. Java, C#, C++ programmers are likely to make simple mistakes until they get used to programming in asynchronous code.

The main thing to remember is to look for callbacks. JavaScript is coded almost entirely using callbacks (or sometimes promises). Here is an example from our library:

Example: This code is broken!

stxx.newChart("IBM");
stxx.addDrawing(myDrawingObject);

In the above example, the addDrawing() function will be run before newChart() is actually completed. This is because newChart() is asynchronous. It must make a network request to fetch data. In JavaScript, the network request occurs in a separate context (thread).

Example: Correct way to write this code:

stxx.newChart("IBM", null, null, function(){
  stxx.addDrawing(myDrawingObject);
});

Now, our code runs inside the callback from newChart. This means that the code runs after the network request has completed and the chart has rendered. By convention, callbacks are usually the last argument to a function. They are sometimes referred to as cb.

It is very important to be aware of JavaScript's scoping rules. Notice how "stxx" is valid in the callback function above. This would be a compile time error in a synchronous language, but in JavaScript a child function can access variables located "above it". This is called a "closure" and is a fundamental concept you should be familiar with.

Tools at Your Disposal

At ChartIQ, we do most of our debugging using Chrome. We recommend that you do the same. Chrome has the best suite of tools and an astonishing number of third-party extensions. If you choose to not use Chrome for debugging, you should still be able to follow along. Before we get to specific examples of using the browser's devtools, we'll take a look at the major browsers and what they offer.

Internet Explorer

Screenshot of the IE Console

Firefox

Screenshot of the FireFox Console

Safari

Screenshot of the Safari Console

Chrome

Screenshot of the Chrome Console

As you can see, the browsers have organized their developer tools in roughly the same manner: DOM explorer, console, debugger, network panel, profiler and some other tabs. Next, we'll explore each of the main tabs in a little more detail.

DOM Explorer

Writing CSS can be a bit maddening. Rescuing us from potential insanity is the "elements" panel. This tab shows the structure of the DOM in a nested tree format. From this panel, you can modify HTML on the fly and dynamically reconfigure CSS styles. In the following example, you will see how easy it is to change the chart background from dark blue to green. Use this technique for rapid prototyping. Of course, changes made in the "elements" tab are not permanent. Once you have settled on an ideal look, save the changes to your CSS file. ​ SCREENSHOT OF CHANGING A CSS PROPERTY, AND THE RESULTSCREENSHOT OF CHANGING A CSS PROPERTY, AND THE RESULT ​ ​ This box is at the bottom of the styles pane. It's very useful for quickly inspecting the alignment of elements. Note how the green shading indicates that padding exists on the element.

SCREENSHOT OF MARGINS AND PADDING

Console

Modern browsers all implement a global object called "console." The most widely used console function is console.log(obj). This function simply prints messages to the browser's dev console. While breakpoints are the most effective debugging method, console.log is useful in many cases (for example, debugging mouse movements).

Often, edge cases exist that need to be logged without disrupting your application. For this purpose, the console object provides an error function. If you come across this situation, it's helpful to console.error(new Error('I ran into an edge case!')). This will print the message along with a handy stack trace, but it won't stop your app from functioning.

SCREENSHOT OF ALL 3 BEING USED

You can also interact with the console by examining and modifying the contents of data in an effort to understand bugs. Use this technique when the chart:

  • isn't displaying data
  • is displaying the wrong data
  • isn't working in some other way

For example, if you type an object's name followed by a dot (e.g., stxx.), the console will show you all of its properties and methods.

examining objects

If you type an object's name and press enter, you can examine the object. You can also do this if the browser is stopped at a breakpoint.

examining objects 2

Here are some common objects you might examine when encountering data errors:

Data
  • masterData (stxx.masterData)

masterData contains the raw data that you have provided to the chart. This includes the OHLC data, as well as any comparison series. The masterData will change and grow as streaming data is pushed onto the end of the chart or if a user scrolls back forcing a pagination request.

MasterData

  • dataSet (stxx.chart.dataSet)

dataSet is the consolidated view of the masterData that the chart uses for display. This will include the calculated values of any studies. This array may be shorter than masterData if a "roll up" of periodicity is in effect. The most common case would be a roll up of daily bars into weekly or monthly bars.

One way to think about dataSet is how it represents the entire chart, including the sections that are off the edge of the screen.

dataSet

  • dataSegment (stxx.chart.dataSegment)

dataSegment is the portion of the dataSet that is currently displayed on the screen. As the chart is panned or zoomed, the dataSegment is updated to reflect the new position in the chart.

dataSegment

  • series (stxx.chart.series)

series is a map of comparison series along with the settings for each series (i.e. color, symbol).

For more information on the data that powers the chart, please see the Data Loading Tutorial.

Display
  • Layout

The layout contains all of the chart settings that impact how the data is displayed. This includes the chartType (bar, candle, line, etc.), chart scale, candleWidth (zoom) and enabled studies. For more information, see Importing and exporting chart layouts.

MasterData

  • Panels

Every chart object has at least one panel (the chart panel). When non-overlay indicators are added to the chart object, additional panels are created.

Source Debugger

The debugger is where you will spend the majority of your time. Be sure to check the "Async" flag in Chrome so that your stack traces work across asynchronous calls (asynchronous debugging).

To effectively code in JavaScript, you must master the following debugger skills:

  • Navigating the sources panel
  • Setting breakpoints
  • Stepping over, into and out of code
  • Examining the contents of variables
  • Understanding the call stack
Setting Breakpoints

A typical breakpoint will pause the code's execution every time the program reaches that line:

breakpoints

If you only want the code to pause in certain circumstances, you can set a conditional breakpoint:

breakpoints

Now the code will only pause if the chart has data in the scrubbed object:

breakpoints

Scope Explorer

When the code pauses at a breakpoint, you have access to the values of all of your variables. The scope explorer will show you:

  • global variables
  • local variables
  • variables accessible from prior closures

scope explorer

If you are unfamiliar with the capabilities of the debugger, please read this introduction.

Network Panel

The network panel is where you'll go if you need to verify any data coming into or leaving your application. We will focus on incoming data that is requested by the QuoteFeed.

Examining quote data as it comes in:

Network Panel Network Panel

Profiler

The profiler should be your first stop for debugging performance issues. Simply run the profiler, conduct an activity and then stop the profiler. The profiler will present a results page. Typically, the topmost function in the results will reveal the culprit. For more information about profiling web applications, click here.

Mobile Debugging

It can be difficult to debug mobile applications because they don't have immediate access to your browser's devtools. Several techniques are available to work around this issue:

  • Chrome provides excellent emulation abilities right inside of the browser. In debugging tools, click on the "toggle device toolbar" icon to switch to mobile mode. Chrome will resize itself and respond to touch events.

  • If you have an Android or iOS device in your possession, you can plug it in and debug it just like you would a web page. Android Instructions. iOS Instructions.

  • When you don't have an actual device, the Android emulator allows you to debug your app/site using Chrome, and the iOS Simulator allows you to debug your app/site using Safari (about halfway down the page you will see instructions).

Troubleshooting Common Errors

Here are some helpful tips to resolve common errors:

  • If the chart is throwing an error, check the top link in the stack trace. This is the shortest path to figuring out what's wrong.
  • If the chart isn't rendering at all, but you can see it in the DOM explorer, make sure that its container has a fixed height (i.e. 100px). HTML elements at the body scope must used fixed heights; nested elements can use percentage heights. In either case, the element must have height for the chart to render properly.
  • If the chart isn't displaying any data, check your network tab to ensure that data is coming in.

    • If data is coming in from your data server, put a breakpoint in the Quotefeed. Also be sure that the data being sent back is compatible with the chart type being displayed. For instance, candlestick charts (type "candle") require Open, High, Low, and Close to render properly.

    • If no data is coming in, check your server.

  • If your QuoteFeed is correctly processing data and passing it to the chart, but you don't see data on the chart, use the console to examine the contents of stxx.chart.dataSegment.
  • If your chart is loading, but it isn't restoring data from previous sessions, ensure that your restoreLayout function is being called. For more, see Chart State Management tutorial.
  • If your chart is loading, but the bars are black and things just look wrong, ensure that chartiq.css is being included properly.
  • When using a quotefeed, CIQ.ChartEngine#newChart will be asynchronous. If you need to do something after the chart is loaded you must do so in the callback returned from newChart().
  • If you encounter an error not listed here, then email us at dev@chartiq.com. We're happy to help!

Tips

  • Putting the line debugger; in your code will halt program execution at that point and bring up the debugger. Your console must be open for this to work.

  • Name your anonymous functions. This improves the readability of the call stack.

  • Don't minify your code when developing.

  • If you minify your code in production, make sure you include source maps to aid in debugging (there is no performance impact by including source maps because they are only loaded when you open the developer tools.)

  • Don't debug obfuscated code. If the error is in an obfuscated part of the library, send the following to support@chartiq.com: JSON.parse(localStorage), a screenshot of the error and the stack trace.

  • If you want to inspect your chart object, but it's isolated inside of a local scope, temporarily modify your code, and assign it to the global window: window.myChartObject=stxx;.

Resources


Next Steps: