Skip to content

Latest commit

 

History

History
335 lines (266 loc) · 7.92 KB

File metadata and controls

335 lines (266 loc) · 7.92 KB

Progress Tracking

This guide covers progress tracking for uploads and downloads.

📊 Progress Callback

The onProgress callback provides real-time progress updates for both uploads and downloads.

Callback Function

onProgress: (percentage: number) => void
  • percentage - Progress value from 0 to 100

📥 Download Progress

Basic Download Progress

import fetch from '@neabyte/fetch'

const response = await fetch.get('https://httpbin.org/bytes/1024', {
  download: true,
  filename: 'file.bin',
  onProgress: (percentage) => {
    console.log(`Download progress: ${percentage}%`)
  }
})

Download with Progress Bar

function updateProgressBar(percentage: number) {
  const bar = '█'.repeat(Math.floor(percentage / 2))
  const space = ' '.repeat(50 - Math.floor(percentage / 2))
  process.stdout.write(`\r[${bar}${space}] ${percentage}%`)
}

const response = await fetch.get('https://httpbin.org/bytes/10240', {
  download: true,
  filename: 'large-file.bin',
  onProgress: updateProgressBar
})

console.log('\nDownload complete!')

Multiple File Downloads

const files = [
  { url: 'https://httpbin.org/bytes/1024', name: 'file1.bin' },
  { url: 'https://httpbin.org/bytes/2048', name: 'file2.bin' },
  { url: 'https://httpbin.org/bytes/4096', name: 'file3.bin' }
]

for (const file of files) {
  console.log(`Downloading ${file.name}...`)
  await fetch.get(file.url, {
    download: true,
    filename: file.name,
    onProgress: (percentage) => {
      console.log(`${file.name}: ${percentage}%`)
    }
  })
}

🚦 Rate Limiting with Progress

Download with Rate Limiting

const response = await fetch.get('https://httpbin.org/bytes/10240', {
  download: true,
  filename: 'large-file.bin',
  maxRate: 100 * 1024, // 100KB/s
  onProgress: (percentage) => {
    console.log(`Download progress: ${percentage}% (rate limited)`)
  }
})

Upload with Rate Limiting

const formData = new FormData()
formData.append('file', fileInput.files[0])

const response = await fetch.post('https://httpbin.org/post', formData, {
  maxRate: 50 * 1024, // 50KB/s
  onProgress: (percentage) => {
    console.log(`Upload progress: ${percentage}% (rate limited)`)
  }
})

Rate Limiting with Progress Bar

function updateProgressBar(percentage: number, rate: string) {
  const bar = '█'.repeat(Math.floor(percentage / 2))
  const space = ' '.repeat(50 - Math.floor(percentage / 2))
  process.stdout.write(`\r[${bar}${space}] ${percentage}% (${rate})`)
}

const response = await fetch.get('https://httpbin.org/bytes/10240', {
  download: true,
  filename: 'file.bin',
  maxRate: 200 * 1024, // 200KB/s
  onProgress: (percentage) => {
    updateProgressBar(percentage, '200KB/s')
  }
})

Dynamic Rate Limiting

class AdaptiveRateLimiter {
  private baseRate: number
  private currentRate: number

  constructor(baseRate: number) {
    this.baseRate = baseRate
    this.currentRate = baseRate
  }

  getRate(): number {
    return this.currentRate
  }

  adjustRate(success: boolean) {
    if (success) {
      this.currentRate = Math.min(this.currentRate * 1.1, this.baseRate * 2)
    } else {
      this.currentRate = Math.max(this.currentRate * 0.9, this.baseRate * 0.5)
    }
  }
}

const rateLimiter = new AdaptiveRateLimiter(100 * 1024) // 100KB/s base

const response = await fetch.get('https://httpbin.org/bytes/10240', {
  download: true,
  filename: 'file.bin',
  maxRate: rateLimiter.getRate(),
  onProgress: (percentage) => {
    console.log(`Progress: ${percentage}% at ${Math.round(rateLimiter.getRate() / 1024)}KB/s`)
  }
})

📤 Upload Progress

Basic Upload Progress

const formData = new FormData()
formData.append('file', fileInput.files[0])

const response = await fetch.post('https://httpbin.org/post', formData, {
  onProgress: (percentage) => {
    console.log(`Upload progress: ${percentage}%`)
  }
})

JSON Upload Progress

const data = {
  name: 'John Doe',
  email: 'john@example.com',
  avatar: 'base64-encoded-image-data'
}

const response = await fetch.post('https://httpbin.org/post', data, {
  onProgress: (percentage) => {
    console.log(`Upload progress: ${percentage}%`)
  }
})

File Upload with Progress

async function uploadFile(file: File) {
  const formData = new FormData()
  formData.append('file', file)

  return await fetch.post('https://httpbin.org/post', formData, {
    onProgress: (percentage) => {
      const bar = '█'.repeat(Math.floor(percentage / 2))
      const space = ' '.repeat(50 - Math.floor(percentage / 2))
      console.log(`\r[${bar}${space}] ${percentage}%`)
    }
  })
}

// Usage
const fileInput = document.getElementById('file') as HTMLInputElement
const file = fileInput.files[0]
if (file) {
  await uploadFile(file)
  console.log('\nUpload complete!')
}

🔄 Combined Upload and Download

Upload with Download Progress

const response = await fetch.post('https://httpbin.org/post', data, {
  onProgress: (percentage) => {
    console.log(`Upload progress: ${percentage}%`)
  }
})

// Process response and download result
const downloadResponse = await fetch.get(response.data.downloadUrl, {
  download: true,
  filename: 'result.pdf',
  onProgress: (percentage) => {
    console.log(`Download progress: ${percentage}%`)
  }
})

Batch Operations with Progress

async function processFiles(files: File[]) {
  const results = []

  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    console.log(`Processing file ${i + 1}/${files.length}: ${file.name}`)

    const response = await fetch.post('https://httpbin.org/post', file, {
      onProgress: (percentage) => {
        console.log(`File ${i + 1} upload: ${percentage}%`)
      }
    })

    results.push(response)
  }

  return results
}

⚙️ Progress Configuration

Custom Progress Handler

class ProgressTracker {
  private totalFiles: number
  private completedFiles: number = 0
  private currentProgress: number = 0

  constructor(totalFiles: number) {
    this.totalFiles = totalFiles
  }

  createProgressCallback(fileIndex: number) {
    return (percentage: number) => {
      this.currentProgress = percentage
      this.updateOverallProgress(fileIndex, percentage)
    }
  }

  private updateOverallProgress(fileIndex: number, percentage: number) {
    const fileWeight = 100 / this.totalFiles
    const fileProgress = (percentage / 100) * fileWeight
    const completedWeight = (this.completedFiles / this.totalFiles) * 100
    const overallProgress = completedWeight + fileProgress

    console.log(`Overall progress: ${Math.round(overallProgress)}%`)
  }

  markFileComplete() {
    this.completedFiles++
  }
}

// Usage
const tracker = new ProgressTracker(3)
const files = [file1, file2, file3]

for (let i = 0; i < files.length; i++) {
  await fetch.post('https://httpbin.org/post', files[i], {
    onProgress: tracker.createProgressCallback(i)
  })
  tracker.markFileComplete()
}

Progress with Error Handling

async function uploadWithProgress(file: File) {
  try {
    const response = await fetch.post('https://httpbin.org/post', file, {
      onProgress: (percentage) => {
        console.log(`Upload: ${percentage}%`)
      }
    })
    console.log('Upload successful!')
    return response
  } catch (error) {
    console.log('Upload failed:', error.message)
    throw error
  }
}

🎯 Best Practices

  • Use progress callbacks for long-running operations
  • Provide visual feedback with progress bars
  • Handle progress errors gracefully
  • Track overall progress for batch operations
  • Use descriptive progress messages
  • Consider user experience when showing progress

🚀 Next Steps