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.
		
		
		
		
		
			
		
			
				
					
					
						
							125 lines
						
					
					
						
							3.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							125 lines
						
					
					
						
							3.4 KiB
						
					
					
				
								'use strict';
							 | 
						|
								
							 | 
						|
								var throttle = require('throttleit');
							 | 
						|
								
							 | 
						|
								function onRequest(context) {
							 | 
						|
								    // Reset dynamic stuff
							 | 
						|
								    context.startedAt = null;
							 | 
						|
								
							 | 
						|
								    context.state = context.request.progressState = null;
							 | 
						|
								
							 | 
						|
								    context.delayTimer && clearTimeout(context.delayTimer);
							 | 
						|
								    context.delayTimer = null;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function onResponse(context, response) {
							 | 
						|
								    // Mark start timestamp
							 | 
						|
								    context.startedAt = Date.now();
							 | 
						|
								
							 | 
						|
								    // Create state
							 | 
						|
								    // Also expose the state throught the request
							 | 
						|
								    // See https://github.com/IndigoUnited/node-request-progress/pull/2/files
							 | 
						|
								    context.state = context.request.progressState = {
							 | 
						|
								        time: {
							 | 
						|
								            elapsed: 0,
							 | 
						|
								            remaining: null
							 | 
						|
								        },
							 | 
						|
								        speed: null,
							 | 
						|
								        percentage: null,
							 | 
						|
								        size: {
							 | 
						|
								            total: Number(response.headers[context.options.lengthHeader]) || null,
							 | 
						|
								            transferred: 0
							 | 
						|
								        }
							 | 
						|
								    };
							 | 
						|
								
							 | 
						|
								    // Delay the progress report
							 | 
						|
								    context.delayTimer = setTimeout(function () {
							 | 
						|
								        context.delayTimer = null;
							 | 
						|
								    }, context.options.delay);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function onData(context, data) {
							 | 
						|
								    context.state.size.transferred += data.length;
							 | 
						|
								
							 | 
						|
								    !context.delayTimer && context.reportState();
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function onEnd(context) {
							 | 
						|
								    /* istanbul ignore if */
							 | 
						|
								    if (context.delayTimer) {
							 | 
						|
								        clearTimeout(context.delayTimer);
							 | 
						|
								        context.delayTimer = null;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    context.request.progressState = context.request.progressContext = null;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function reportState(context) {
							 | 
						|
								    var state;
							 | 
						|
								
							 | 
						|
								    // Do nothing if still within the initial delay or if already finished
							 | 
						|
								    if (context.delayTimer || !context.request.progressState) {
							 | 
						|
								        return;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    state = context.state;
							 | 
						|
								    state.time.elapsed = (Date.now() - context.startedAt) / 1000;
							 | 
						|
								
							 | 
						|
								    // Calculate speed only if 1s has passed
							 | 
						|
								    if (state.time.elapsed >= 1) {
							 | 
						|
								        state.speed = state.size.transferred / state.time.elapsed;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Calculate percentage & remaining only if we know the total size
							 | 
						|
								    if (state.size.total != null) {
							 | 
						|
								        state.percentage = Math.min(state.size.transferred, state.size.total) / state.size.total;
							 | 
						|
								
							 | 
						|
								        if (state.speed != null) {
							 | 
						|
								            state.time.remaining = state.percentage !== 1 ? (state.size.total / state.speed) - state.time.elapsed : 0;
							 | 
						|
								            state.time.remaining = Math.round(state.time.remaining * 1000) / 1000;  // Round to 4 decimals
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    context.request.emit('progress', state);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								function requestProgress(request, options) {
							 | 
						|
								    var context;
							 | 
						|
								
							 | 
						|
								    if (request.progressContext) {
							 | 
						|
								        return request;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (request.response) {
							 | 
						|
								        throw new Error('Already got response, it\'s too late to track progress');
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Parse options
							 | 
						|
								    options = options || {};
							 | 
						|
								    options.throttle = options.throttle == null ? 1000 : options.throttle;
							 | 
						|
								    options.delay = options.delay || 0;
							 | 
						|
								    options.lengthHeader = options.lengthHeader || 'content-length';
							 | 
						|
								
							 | 
						|
								    // Create context
							 | 
						|
								    context = {};
							 | 
						|
								    context.request = request;
							 | 
						|
								    context.options = options;
							 | 
						|
								    context.reportState = throttle(reportState.bind(null, context), options.throttle);
							 | 
						|
								    // context.startedAt = null;
							 | 
						|
								    // context.state = null;
							 | 
						|
								    // context.delayTimer = null;
							 | 
						|
								
							 | 
						|
								    // Attach listeners
							 | 
						|
								    request
							 | 
						|
								    .on('request', onRequest.bind(null, context))
							 | 
						|
								    .on('response', onResponse.bind(null, context))
							 | 
						|
								    .on('data', onData.bind(null, context))
							 | 
						|
								    .on('end', onEnd.bind(null, context));
							 | 
						|
								
							 | 
						|
								    request.progressContext = context;
							 | 
						|
								
							 | 
						|
								    return request;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								module.exports = requestProgress;
							 | 
						|
								
							 |