You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							141 lines
						
					
					
						
							2.9 KiB
						
					
					
				
			
		
		
	
	
							141 lines
						
					
					
						
							2.9 KiB
						
					
					
				var async = require('./async.js'); | 
						|
 | 
						|
// API | 
						|
module.exports = { | 
						|
  iterator: wrapIterator, | 
						|
  callback: wrapCallback | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Wraps iterators with long signature | 
						|
 * | 
						|
 * @this    ReadableAsyncKit# | 
						|
 * @param   {function} iterator - function to wrap | 
						|
 * @returns {function} - wrapped function | 
						|
 */ | 
						|
function wrapIterator(iterator) | 
						|
{ | 
						|
  var stream = this; | 
						|
 | 
						|
  return function(item, key, cb) | 
						|
  { | 
						|
    var aborter | 
						|
      , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key)) | 
						|
      ; | 
						|
 | 
						|
    stream.jobs[key] = wrappedCb; | 
						|
 | 
						|
    // it's either shortcut (item, cb) | 
						|
    if (iterator.length == 2) | 
						|
    { | 
						|
      aborter = iterator(item, wrappedCb); | 
						|
    } | 
						|
    // or long format (item, key, cb) | 
						|
    else | 
						|
    { | 
						|
      aborter = iterator(item, key, wrappedCb); | 
						|
    } | 
						|
 | 
						|
    return aborter; | 
						|
  }; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Wraps provided callback function | 
						|
 * allowing to execute snitch function before | 
						|
 * real callback | 
						|
 * | 
						|
 * @this    ReadableAsyncKit# | 
						|
 * @param   {function} callback - function to wrap | 
						|
 * @returns {function} - wrapped function | 
						|
 */ | 
						|
function wrapCallback(callback) | 
						|
{ | 
						|
  var stream = this; | 
						|
 | 
						|
  var wrapped = function(error, result) | 
						|
  { | 
						|
    return finisher.call(stream, error, result, callback); | 
						|
  }; | 
						|
 | 
						|
  return wrapped; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Wraps provided iterator callback function | 
						|
 * makes sure snitch only called once, | 
						|
 * but passes secondary calls to the original callback | 
						|
 * | 
						|
 * @this    ReadableAsyncKit# | 
						|
 * @param   {function} callback - callback to wrap | 
						|
 * @param   {number|string} key - iteration key | 
						|
 * @returns {function} wrapped callback | 
						|
 */ | 
						|
function wrapIteratorCallback(callback, key) | 
						|
{ | 
						|
  var stream = this; | 
						|
 | 
						|
  return function(error, output) | 
						|
  { | 
						|
    // don't repeat yourself | 
						|
    if (!(key in stream.jobs)) | 
						|
    { | 
						|
      callback(error, output); | 
						|
      return; | 
						|
    } | 
						|
 | 
						|
    // clean up jobs | 
						|
    delete stream.jobs[key]; | 
						|
 | 
						|
    return streamer.call(stream, error, {key: key, value: output}, callback); | 
						|
  }; | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Stream wrapper for iterator callback | 
						|
 * | 
						|
 * @this  ReadableAsyncKit# | 
						|
 * @param {mixed} error - error response | 
						|
 * @param {mixed} output - iterator output | 
						|
 * @param {function} callback - callback that expects iterator results | 
						|
 */ | 
						|
function streamer(error, output, callback) | 
						|
{ | 
						|
  if (error && !this.error) | 
						|
  { | 
						|
    this.error = error; | 
						|
    this.pause(); | 
						|
    this.emit('error', error); | 
						|
    // send back value only, as expected | 
						|
    callback(error, output && output.value); | 
						|
    return; | 
						|
  } | 
						|
 | 
						|
  // stream stuff | 
						|
  this.push(output); | 
						|
 | 
						|
  // back to original track | 
						|
  // send back value only, as expected | 
						|
  callback(error, output && output.value); | 
						|
} | 
						|
 | 
						|
/** | 
						|
 * Stream wrapper for finishing callback | 
						|
 * | 
						|
 * @this  ReadableAsyncKit# | 
						|
 * @param {mixed} error - error response | 
						|
 * @param {mixed} output - iterator output | 
						|
 * @param {function} callback - callback that expects final results | 
						|
 */ | 
						|
function finisher(error, output, callback) | 
						|
{ | 
						|
  // signal end of the stream | 
						|
  // only for successfully finished streams | 
						|
  if (!error) | 
						|
  { | 
						|
    this.push(null); | 
						|
  } | 
						|
 | 
						|
  // back to original track | 
						|
  callback(error, output); | 
						|
}
 | 
						|
 |