приостановить и возобновить XMLHttpRequest - PullRequest
0 голосов
/ 09 ноября 2019

Вот рабочий код для предварительной загрузки видеофайла MP4 в браузер через XHR2. Всякий раз, когда мы выполняем preloadMe();, видео начинает предварительно загружаться и составлять событие прогресса. и как файл полностью загруженный preload.oncomplete запускается, и мы можем обнаружить это.

Проблема в том, что мне нужна возможность pause и resume процесса предварительной загрузки? использование метода abort завершает весь запрос. Я хочу иметь возможность возобновить работу позже и продолжить загрузку файла в тот момент, когда я его приостановил.

Буду признателен за любые предложения!

Примечание: практического ответа по StackOverflow вэтот предмет.

Вот основной код:

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.Preload = factory());
}(this, (function () { 'use strict';

    function preloadOne(url, done) {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.responseType = 'blob';
        xhr.onprogress = event => {
            if (!event.lengthComputable) return false
            let item = this.getItemByUrl(event.target.responseURL);
            item.completion = parseInt((event.loaded / event.total) * 100);
            item.downloaded = event.loaded;
            item.total = event.total;
            this.updateProgressBar(item);
        };
        xhr.onload = event => {
            let type = event.target.response.type;
            let blob = new Blob([event.target.response], { type: type });
            let url = URL.createObjectURL(blob);
            let responseURL = event.target.responseURL;
            let item = this.getItemByUrl(responseURL);
            item.blobUrl = url;
            item.fileName = responseURL.substring(responseURL.lastIndexOf('/') + 1);
            item.type = type;
            item.size = blob.size;
            done(item);
        };
        xhr.send();
    }

    function updateProgressBar(item) {
        var sumCompletion = 0;
        var maxCompletion = this.status.length * 100;

        for (var itemStatus of this.status) {
            if (itemStatus.completion) {
                sumCompletion += itemStatus.completion;
            }
        }
        var totalCompletion = parseInt((sumCompletion / maxCompletion) * 100);

        if (!isNaN(totalCompletion)) {
            this.onprogress({
                progress: totalCompletion,
                item: item
            });
        }
    }

    function getItemByUrl(rawUrl) {
        for (var item of this.status) {
            if (item.url == rawUrl) return item
        }
    }

    function fetch(list) {  
        return new Promise((resolve, reject) => {
            this.loaded = list.length;
            for (let item of list) {
                this.status.push({ url: item });
                this.preloadOne(item, item => {
                    this.onfetched(item);
                    this.loaded--;
                    if (this.loaded == 0) {
                        this.oncomplete(this.status);
                        resolve(this.status);
                    }
                });
            }
        })
    }

    function Preload() {
        return {
            status: [],
            loaded: false,
            onprogress: () => {},
            oncomplete: () => {},
            onfetched: () => {},
            fetch,
            updateProgressBar,
            preloadOne,
            getItemByUrl
        }
    }

    return Preload;

})));

А вот функция для запуска предварительной загрузки:

function preloadMe(){

const preload = Preload();

preload.fetch([
    'https.../video.mp4'

]).then(items => {
  // use either a promise or 'oncomplete'
  console.log(items);
});

preload.oncomplete = items => {
  console.log(items);
  console.log("The video has been preloaded!");
}

preload.onprogress = event => {
  console.log(event.progress + '%');
}

preload.onfetched = item => {
  console.log(item);
}
};
...