function visitContacts(contactSelection, visitor) {
    var deferred = $.Deferred();
    var request = _(requestTemplate).clone();
    if (contactSelection.start_key) {
      request.start_key = contactSelection.start_key;
    }
    request.limit = requestSelectionLimit;
    
    function sendQuery() {
      serviceRequest('query_contacts', request).done(doneQuery).fail(failQuery);
    }
    
    function doneQuery(response) {
      var isLastQuery = (response.contacts.length < requestSelectionLimit);
      
      // Send out request for the next page of data, if it exists.
      if (!isLastQuery) {
        request.start_key = response.last_key;
        sendQuery();
      }
      
      // Invoke the visitor with the returned data for this viewpoint.
      _(response.contacts).each(function (c) {
        if ('contact_user_id' in c) {
          // For the sake of consistent ids, change 'contact_user_id' to 'user_id'. 
          c.user_id = c.contact_user_id;
          delete c.contact_user_id;
        }
        
        visitor(c);
      });
      
      // If this was the last page of the query, resolve this method's promise.
      if (isLastQuery) deferred.resolve();
    }
    
    function failQuery(jqHxr, textStatus) {
      deferred.reject('Error from visitContacts: ' + textStatus);
    }
    
    sendQuery();
    return deferred;
  }
/**
   * Queries the service for contact metadata and invokes the visitor function once with each 
   * contact returned.  Paging is handled transparently by this function.
   *
   * @memberof viewfinder.query
   * @param {Object} contactSelection A viewfinder contact invalidation.
   * @param {Function} visitor A visitor function which will be invoked once for each user
   *   returned by the query.
   * 
   * @returns {jQuery.Deferred} A jQuery deferred object which will resolve when all user data has
   *   been visited.
   */
Queries the service for contact metadata and invokes the visitor function once with each
contact returned.  Paging is handled transparently by this function.

@memberof viewfinder.query
@param {Object} contactSelection A viewfinder contact invalidation.
@param {Function} visitor A visitor function which will be invoked once for each user
returned by the query.

@returns {jQuery.Deferred} A jQuery deferred object which will resolve when all user data has
been visited.
Queries the service for contact metadata and invokes the visitor function once with each contact returned . Paging is handled transparently by this function . @memberof viewfinder . query @param { Object } contactSelection A viewfinder contact invalidation . @param { Function } visitor A visitor function which will be invoked once for each user returned by the query . @returns { jQuery . Deferred } A jQuery deferred object which will resolve when all user data has been visited .
function visitContacts(contactSelection, visitor) {
    var deferred = $.Deferred();
    var request = _(requestTemplate).clone();
    if (contactSelection.start_key) {
      request.start_key = contactSelection.start_key;
    }
    request.limit = requestSelectionLimit;
    function sendQuery() {
      serviceRequest('query_contacts', request).done(doneQuery).fail(failQuery);
    }
    function doneQuery(response) {
      var isLastQuery = (response.contacts.length < requestSelectionLimit);
      if (!isLastQuery) {
        request.start_key = response.last_key;
        sendQuery();
      }
      _(response.contacts).each(function (c) {
        if ('contact_user_id' in c) {
          c.user_id = c.contact_user_id;
          delete c.contact_user_id;
        }
        visitor(c);
      });
      if (isLastQuery) deferred.resolve();
    }
    function failQuery(jqHxr, textStatus) {
      deferred.reject('Error from visitContacts: ' + textStatus);
    }
    sendQuery();
    return deferred;
  }
function visitContacts ( contactSelection , visitor ) { var deferred = $ . Deferred ( ) ; var request = _ ( requestTemplate ) . clone ( ) ; if ( contactSelection . start_key ) { request . start_key = contactSelection . start_key ; } request . limit = requestSelectionLimit ; function sendQuery ( ) { serviceRequest ( 'query_contacts' , request ) . done ( doneQuery ) . fail ( failQuery ) ; } function doneQuery ( response ) { var isLastQuery = ( response . contacts . length < requestSelectionLimit ) ; if ( ! isLastQuery ) { request . start_key = response . last_key ; sendQuery ( ) ; } _ ( response . contacts ) . each ( function ( c ) { if ( 'contact_user_id' in c ) { c . user_id = c . contact_user_id ; delete c . contact_user_id ; } visitor ( c ) ; } ) ; if ( isLastQuery ) deferred . resolve ( ) ; } function failQuery ( jqHxr , textStatus ) { deferred . reject ( 'Error from visitContacts: ' + textStatus ) ; } sendQuery ( ) ; return deferred ; }
Queries the service for contact metadata and invokes the visitor function once with each
 contact returned.
Queries the service for contact metadata and invokes the visitor function once with each contact returned .
// Send out request for the next page of data, if it exists. // Invoke the visitor with the returned data for this viewpoint. // For the sake of consistent ids, change 'contact_user_id' to 'user_id'.  // If this was the last page of the query, resolve this method's promise.