function readFileList( list, options, clbk ) {
	var pending;
	var results;
	var errFLG;
	var count;
	var opts;
	var len;
	var cb;
	var i;

	if ( !isStringArray( list ) ) {
		throw new TypeError( format( 'invalid argument. First argument must be an array of strings. Value: `%s`.', list ) );
	}
	if ( arguments.length < 3 ) {
		opts = {};
		cb = options;
	} else {
		if ( isString( options ) ) {
			opts = options;
		} else {
			opts = assign( {}, options );
		}
		cb = clbk;
	}
	if ( !isFunction( cb ) ) {
		throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', cb ) );
	}
	len = list.length;

	results = new Array( len );
	pending = {};
	count = 0;

	debug( 'Reading %d files...', len );
	for ( i = 0; i < len; i++ ) {
		debug( 'Reading file: %s (%d of %d).', list[ i ], i+1, len );
		readFile( list[ i ], opts, getCallback( i ) );
	}

	/**
	* Returns a callback to be invoked upon reading a file.
	*
	* @private
	* @param {NonNegativeInteger} idx - index
	* @returns {Callback} callback
	*/
	function getCallback( idx ) {
		var retries;
		var file;
		var k;

		file = list[ idx ];
		k = idx + 1;
		retries = 0;

		/**
		* Retries reading a file.
		*
		* @private
		*/
		function retry() {
			delete pending[ idx ];
			debug( 'Reading file: %s (%d of %d). Retry: %d of %d.', file, k, len, retries, MAX_RETRIES );
			readFile( file, opts, onRead );
		}

		/**
		* Callback to be invoked upon reading a file.
		*
		* @private
		* @param {(Error|null)} error - error object
		* @param {(Buffer|string)} data - file data
		* @returns {void}
		*/
		function onRead( error, data ) {
			var d;
			if ( errFLG ) {
				debug( 'An error has already been returned. Discarding data for file: %s (%d of %d).', file, k, len );
				return; // prevents `done()` from being called more than once
			}
			if ( error ) {
				debug( 'Encountered an error when reading %s (%d of %d). Error: %s', file, k, len, error.message );
				if (
					error.code === 'EMFILE' || // current process
					error.code === 'ENFILE'    // across entire system
				) {
					retries += 1;
					if ( retries > MAX_RETRIES ) {
						debug( 'Maximum number of retries exceeded. Too many open files.' );
						error = new Error( 'unexpected error. Max retries exceeded. Too many open files.' );
						return done( error );
					}
					d = delay( retries, MAX_DELAY );
					debug( 'Too many open files. Will retry reading file %d of %d in %s seconds.', k, len, d/1000 );
					pending[ idx ] = setTimeout( retry, d );
					return;
				}
				return done( error );
			}
			debug( 'Successfully read file: %s (%d of %d).', file, k, len );
			results[ idx ] = {
				'file': file,
				'data': data
			};
			count += 1;
			debug( 'Read %d of %d files.', count, len );
			if ( count === len ) {
				return done();
			}
		}

		return onRead;
	}

	/**
	* Callback invoked upon completion.
	*
	* @private
	* @param {Error} [error] - error object
	* @returns {void}
	*/
	function done( error ) {
		clearPending( pending );
		if ( error ) {
			errFLG = true;
			return cb( error );
		}
		debug( 'Successfully read all files.' );
		cb( null, results );
	}
}
Asynchronously reads the entire contents of each file in a file list.

@param {StringArray} list - list of file paths
@param {(Object|string)} [options] - options
@param {(string|null)} [options.encoding] - file encoding
@param {string} [options.flag] - file status flag
@param {Function} clbk - callback to invoke after reading file contents
@throws {TypeError} first argument must be an array of strings
@throws {TypeError} callback argument must be a function

@example
var list = [ __filename ];

readFileList( list, onFiles );

function onFiles( error, files ) {
    if ( error ) {
        throw error;
    }
    console.dir( files );
}