UNPKG

ipull

Version:

The only file downloader you'll ever need. For node.js and the browser, CLI and library for fast and reliable file downloads.

94 lines 3.23 kB
import { ChunkStatus } from "../../types.js"; import { promiseWithResolvers } from "../../utils/promiseWithResolvers.js"; export default class BaseDownloadProgram { savedProgress; _downloadSlice; _aborted = false; _parallelStreams; _reload; _activeDownloads = []; constructor(_savedProgress, _downloadSlice) { this._downloadSlice = _downloadSlice; this.savedProgress = _savedProgress; this._parallelStreams = this.savedProgress.parallelStreams; } get parallelStreams() { return this._parallelStreams; } set parallelStreams(value) { const needReload = value > this._parallelStreams; this._parallelStreams = value; if (needReload) { this._reload?.(); } } incParallelStreams() { this.parallelStreams = this._activeDownloads.length + 1; } decParallelStreams() { this.parallelStreams = this._activeDownloads.length - 1; } waitForStreamToEnd() { return Promise.race(this._activeDownloads); } async download() { if (this._parallelStreams === 1) { return await this._downloadSlice(0, this.savedProgress.chunks.length); } this._createFirstSlices(); while (!this._aborted) { if (this._activeDownloads.length >= this._parallelStreams) { await this._waitForStreamEndWithReload(); continue; } const slice = this._createOneSlice(); if (slice == null) { if (this._activeDownloads.length === 0) { break; } await this._waitForStreamEndWithReload(); continue; } this._createDownload(slice); } } async _waitForStreamEndWithReload() { const promiseResolvers = promiseWithResolvers(); this._reload = promiseResolvers.resolve; return await Promise.race(this._activeDownloads.concat([promiseResolvers.promise])); } _createDownload(slice) { const promise = this._downloadSlice(slice.start, slice.end); this._activeDownloads.push(promise); promise.then(() => { this._activeDownloads.splice(this._activeDownloads.indexOf(promise), 1); }); } /** * Create all the first slices at one - make sure they will not overlap to reduce stream aborts at later stages */ _createFirstSlices() { const slices = []; for (let i = 0; i < this.parallelStreams; i++) { const slice = this._createOneSlice(); if (slice) { const lastSlice = slices.find(x => x.end > slice.start && x.start < slice.start); if (lastSlice) { lastSlice.end = slice.start; } this.savedProgress.chunks[slice.start] = ChunkStatus.IN_PROGRESS; slices.push(slice); } else { break; } } for (const slice of slices) { this._createDownload(slice); } } abort() { this._aborted = true; } } //# sourceMappingURL=base-download-program.js.map