In each of the seven chapters of this interactive course, you can watch an overview video teaching you the latest techniques, and follow a series of challenges where your knowledge will be put to the test. We've integrated the Chrome DevTools themselves into the course, so as you explore the functionality within them, you'll get immediate feedback and earn points and badges.

Even regular users of the Chrome DevTools may be surprised to find some lesser-known features from this course that can really boost productivity. You'll learn a debugging workflow to go from an uncaught exception to a live fix without ever refreshing your app. In addition, the course will share time-saving tricks to improve your efficiency while debugging CSS, improving reflow issues, and interpreting your network and JavaScript bottlenecks. You'll also uncover the DOM bottlenecks that are blocking you from delivering a slick 60 FPS experience.

We hope you’ll try out the Discover DevTools course and see how Chrome DevTools can make you a more productive developer.

Posted by Paul Irish, Senior Developer Advocate (completed the course in 14:52) and Peter Lubbers, Program Manager (best time: 15:05)

The latest Dart SDK now provides a cohesive API for asynchronous programming. Some of the new or improved classes in this release include Stream, a sequence of asynchronous events, and Future, a single asynchronous result.

The Stream class is new and delivers on a common developer request for a more unified approach to events. An event can be any Dart object, which makes Streams very flexible. Consumers of a Stream can listen for events, and streams can be piped, transformed, filtered, and more. We are working to apply them across HTML, I/O, isolates, and more. Here is an example of using streams with the HTML library, treating clicks as a stream of events:

query('#button').onClick.listen((e) => submitForm());



Here is an example of streaming the contents of a file. Notice how streams can be transformed.

Stream<int> stream = ...
stream
  .transform(new StringDecoder())
  .transform(new LineTransformer())
  .listen((String line) { /* Do something with line. */ },
          onDone: () { /* No more lines */ },
          onError: (e) { /* Error on input. */ });



The Future class, which represents a single value available in the future, was cleaned up and is much easier to use. In many cases this allows you to write asynchronous code very similar to its synchronous counterpart:

// Synchronous code, does not use Future
bool writeFile(String data, File file) {
 try {
  var io = file.openSync(FileMode.WRITE);
  io.writeStringSync(data);
  io.closeSync();
  return true;
 } catch (error) {
  return false;
 }
}



// Asynchronous code, does use Future
Future<bool> writeFile(String data,
                       File file) {
 return file.open(FileMode.WRITE)
   .then((io) => io.writeString(data))
   .then((io) => io.close())
   .then((io) => true)
   .catchError((error) => false);
}



Some of these changes are not backwards compatible. Luckily, you can use Dart Editor's Clean Up feature to help automatically port your code from the old API to the new API. Here is an example of Clean Up at work:

Over the following months we will continue to work on the libraries, applying the new asynchronous models. We always appreciate the feedback, please let us know what you think at dartbug.com and [email protected].

To get started, you can download the Dart SDK, learn about the language and libraries, and follow our tutorials. If you already have Dart Editor, it can auto-update to the latest release for you.

The latest Dart SDK now provides a cohesive API for asynchronous programming. Some of the new or improved classes in this release include Stream, a sequence of asynchronous events, and Future, a single asynchronous result.

The Stream class is new and delivers on a common developer request for a more unified approach to events. An event can be any Dart object, which makes Streams very flexible. Consumers of a Stream can listen for events, and streams can be piped, transformed, filtered, and more. We are working to apply them across HTML, I/O, isolates, and more. Here is an example of using streams with the HTML library, treating clicks as a stream of events:

query('#button').onClick.listen((e) => submitForm());

Here is an example of streaming the contents of a file. Notice how streams can be transformed.

Stream<int> stream = ...
stream
  .transform(new StringDecoder())
  .transform(new LineTransformer())
  .listen((String line) { /* Do something with line. */ },
          onDone: () { /* No more lines */ },
          onError: (e) { /* Error on input. */ });

The Future class, which represents a single value available in the future, was cleaned up and is much easier to use. In many cases this allows you to write asynchronous code very similar to its synchronous counterpart:

// Synchronous code, does not use Future
bool writeFile(String data, File file) {
 try {
  var io = file.openSync(FileMode.WRITE);
  io.writeStringSync(data);
  io.closeSync();
  return true;
 } catch (error) {
  return false;
 }
}

// Asynchronous code, does use Future
Future<bool> writeFile(String data,
                       File file) {
 return file.open(FileMode.WRITE)
   .then((io) => io.writeString(data))
   .then((io) => io.close())
   .then((io) => true)
   .catchError((error) => false);
}

Some of these changes are not backwards compatible. Luckily, you can use Dart Editor's Clean Up feature to help automatically port your code from the old API to the new API. Here is an example of Clean Up at work:

Over the following months we will continue to work on the libraries, applying the new asynchronous models. We always appreciate the feedback, please let us know what you think at dartbug.com and misc@dartlang.org.

To get started, you can download the Dart SDK, learn about the language and libraries, and follow our tutorials. If you already have Dart Editor, it can auto-update to the latest release for you.