docs: function(options, callbacks) {
              var period = options.period || 500; // ms
              
              if (utils.isFunction(callbacks)) {
                  callbacks = {
                      done: callbacks
                  };
              }
              
              var noCallbacksAfterReady = (
                  !callbacks.progress &&
                  !callbacks.done &&
                  !callbacks.failed &&
                  !callbacks.error
              );
              
              callbacks.ready = callbacks.ready || function() {};
              callbacks.progress = callbacks.progress || function() {};
              callbacks.done = callbacks.done || function() {};
              callbacks.failed = callbacks.failed || function() {};
              callbacks.error = callbacks.error || function() {};
              
              // For use by tests only
              callbacks._preready = callbacks._preready || function() {};
              callbacks._stoppedAfterReady = callbacks._stoppedAfterReady || function() {};
              
              var that = this;
              var emittedReady = false;
              var doneLooping = false;
              Async.whilst(
                  function() { return !doneLooping; },
                  function(nextIteration) {
                      that.fetch(function(err, job) {
                          if (err) {
                              nextIteration(err);
                              return;
                          }
                          
                          var dispatchState = job.properties().dispatchState;
                          var notReady = dispatchState === "QUEUED" || dispatchState === "PARSING";
                          if (notReady) {
                              callbacks._preready(job);
                          }
                          else {
                              if (!emittedReady) {
                                  callbacks.ready(job);
                                  emittedReady = true;
                                  
                                  // Optimization: Don't keep polling the job if the
                                  // caller only cares about the `ready` event.
                                  if (noCallbacksAfterReady) {
                                      callbacks._stoppedAfterReady(job);
                                      
                                      doneLooping = true;
                                      nextIteration();
                                      return;
                                  }
                              }
                              
                              callbacks.progress(job);
                              
                              var props = job.properties();
                              
                              if (dispatchState === "DONE" && props.isDone) {
                                  callbacks.done(job);
                                  
                                  doneLooping = true;
                                  nextIteration();
                                  return;
                              }
                              else if (dispatchState === "FAILED" && props.isFailed) {
                                  callbacks.failed(job);
                                  
                                  doneLooping = true;
                                  nextIteration();
                                  return;
                              }
                          }
                          
                          Async.sleep(period, nextIteration);
                      });
                  },
                  function(err) {
                      if (err) {
                          callbacks.error(err);
                      }
                  }
              );
          }