-
Notifications
You must be signed in to change notification settings - Fork 0
Upgrading to 3.0
D3 3.0 is the first major release since 2.0 was released last August. Since 2.0.0, there have been 10 minor releases and 37 patch releases. 3.0 includes significant new features and improvements, but in accordance with semantic versioning, this major release also includes several backwards-incompatibilities. This document will guide you on how to upgrade from 2.x to 3.0.
Most changes to D3 are carefully designed to be backwards-compatible, which makes it easier to upgrade. If you’ve been linking to the official d3.v2.js, you’ve been getting bug fixes, performance improvements, and new features automatically. Unfortunately, not all changes can be made backwards-compatible; periodically, these potentially disruptive changes are needed to keep the API and the code lean by removing deprecated, broken or confusing functionality.
One of the first things you are likely to notice is that the d3.xhr callback interface has changed. In 2.x, you might have written code like this:
d3.json("my-data.json", function(data) {
console.log("there are " + data.length + " elements in my dataset");
});In 3.0, the callback function now takes an additional argument, error. If an error occurs fetching the requested resource, the error argument will contain information that you can use to diagnose the problem or inform the user, such as whether the file is missing or the server is unavailable. The second argument contains the contents of the resource, as before. So, the simplest fix is to add "error, " to your callback:
d3.json("my-data.json", function(error, data) {
console.log("there are " + data.length + " elements in my dataset");
});But this code still ignores the error, so you might prefer to handle errors gracefully:
d3.json("my-data.json", function(error, data) {
if (error != null) return console.log("there was an error loading the data: " + error);
console.log("there are " + data.length + " elements in my dataset");
});The reason for this change is two-fold. First, it adopts the standard {error, result} asynchronous callback convention established by Node.js. This makes it familiar to JavaScript developers. Better yet, it means you can use helpers for asynchronous JavaScript, such as Queue.js. For example, say you wanted to load two resources for a map visualization, a GeoJSON file "us-states.json" and a data file "us-state-populations.tsv". In 2.x, you probably would have loaded these serially by nesting callbacks:
d3.json("us-states.json", function(states) {
d3.tsv("us-state-populations.tsv", function(statePopulations) {
// display map here
});
});Loading resources serially is slow! It's better to parallelize those requests, which is now easy:
queue()
.defer(d3.json, "us-states.json")
.defer(d3.tsv, "us-state-populations.tsv")
.await(ready);
function ready(error, states, statePopulations) {
// display map here
}The last reason this change was made is to make it more obvious that these requests can fall. That first argument, error, is a nagging reminder that you might want to handle errors when loading resources by displaying a suitable notification to your users or retrying the request. It also means you can now distinguish between a successfully-loaded JSON file that contains null and an error.
D3’s transition subsystem has been significantly overhauled for 3.0 to make it easier to construct complex sequences of transitions. In most cases, you’re not likely to notice any of these changes, despite being strictly backwards-incompatible. If you are using transitions extensively, I highly recommend reading my tutorial, Working with Transitions.
The first significant change is that transition.attr, transition.style and transition.text now evaluate their property functions immediately. This makes them behave just like their selection equivalents. However, in 2.x, these functions were evaluated asynchronously when the transition started! While deferred evaluation is occasionally what you want, immediate evaluation is much easier to understand and debug. It also means that you can easily specify transitions that depend on external state, such as scale domains in chained transitions of data and axes.