when debug

Brian Cavalier edited this page Jun 6, 2013 · 12 revisions

DEPRECATED: when/debug is deprecated and will be removed. Use when/monitor/console instead.

Debugging asynchronous operations is tricky, and debugging a system with lots of asynchrony, which is becoming the norm in highly interactive web applications, can be downright painful.

The when/debug module is an evolving experiment in providing basic debugging aids when using Promises. The near-term goal is to evaluate debugging approaches that may be useful. The longer term goal is to keep the approaches that prove useful, and ditch the ones that don't.

IMPORTANT: This module may change drastically, and without warning, in future releases. You shouldn't depend on any functionality it provides.

MORE IMPORTANT: Don't use this module in a production environment. It may break your code. Always test against the non-debug when before deploying production code.

What does it do?

The when/debug module is a drop-in replacement for the when module. It has exactly the same API as when, but adds the following:

  1. when.defer accepts an optional id parameter that can be used to "tag" a promise (and it's associated deferred and resolver) so you can more easily differentiate between promises in debugging output.

    NOTE: the normal (i.e. non-debug) when.defer() will ignore this id entirely. So, while keeping the id in your code is safe, you should probably remove it for production.

  2. Any promise created using when.defer(<optional id>) will log information about its status and rejection value to the console when it is rejected.

  3. Promises, Deferreds, and Resolvers have a toString() that creates a string containing the id (see #1 above), and information about the state of the promise (pending, resolved, or rejected), its resolution value if resolved, or its rejection value if rejected.

  4. It catches exceptions that typically represent coding mistakes, such as SyntaxError, ReferenceError, and the like, and rethrows them in a way that ensures they will propagate up to the host env, generating a loud stack trace.

    You can configure the exact set of exception types that will be rethrown to the host env:

when.debug = {
	exceptionsToRethrow: {
		// Keys are the names of exception types to propagate;
		// set the value to truthy.  Any other exceptions
		// will be captured and transformed into rejections.
		// The defaults used by when/debug are:
		RangeError: true,
		ReferenceError: true,
		SyntaxError: true,
		TypeError: true
	}
}
  1. It allows when() and all the when.*() methods to debug (at least minimally) foreign promises when it assimilates them.

  2. It allows you to set a global rejection callback that will be called when any promise rejects. So, you an setup your own debugging output if you want.

var when = require('when/debug');
when.debug = {
	reject: function(promise, rejectionReason, auxError) {
		// promise - the promise that was rejected
		// rejectionValue - the reason with which the promise was
		//   rejected.
		// auxError - an Error object created by when/debug
		//   containing a stack trace (auxError.stack) that
		//   leads to the point at which the promise was rejected
	}
}

How to use it

To use it, load when/debug instead of when. Depending on your environment, and the scope of the debugging you want, there are a few ways to do that.

AMD

  1. If using a package config, change main to point to debug instead of when:

    packages: [
    	{ name: 'when', location: 'path/to/whenDir', main: 'debug' },
    	// ... other packages ...
    ]
  2. If using a path, point to debug:

    NOTE: Using a path does not work with some AMD loaders. Please use a package config as above.

    paths: {
    	when: 'path/to/when/debug',
    	// ... other paths ...
    }
  3. You can also use when/debug in selective places for more targetted debugging by changing dependencies on when to when/debug:

    // In a module you want to debug
    define(['when/debug', ...], function(when, ...) {
    	// Your module here
    });

CommonJS

  1. CommonJS doesn't have package or path mapping indirection (as AMD does), so currently, it's a bit more invasive to use when/debug everywhere in your app.

    Modify the main property in when.js's package.json file:

    "main": "./debug"

    Yes, this stinks :) We're working on a better way!

  2. To use when/debug more selectively, simply load it instead of when:

    // In a module you want to debug
    //var when = require('when');
    var when = require('when/debug');

Browser script tag

  1. Point your script tag at debug.js instead of when.js:

    <!-- <script src="path/to/when/when.js"></script> -->
    <script src="path/to/when/debug.js"></script>