Элемент в системном объекте (JavaScript)

Положил в системный объект DOM элемент.

Вывожу в консоль xhr, который имеет элемент progressbar.
Но this.progressbar - undefined. Почему?

var File = {



    add: function() {

        let form = document.createElement('input');
        form.type = 'file';
        form.click();

        form.onchange = function() {

            File.upload(this.files[0])

            .Before(function() { this.progressbar =
            document.querySelector('progress'); })

            // Туть undefined, хотя this показывает его наличие
            .Progress(function() { console.log(this.progressbar); });
        }
    },



    upload: function(file) {

        let form = new FormData();
        form.append('file', file);

        function post(xhr) {

            xhr.open('POST', window.location.origin);

            xhr.Before = function(c) { xhr.Before = c; return this; };
            xhr.Progress = function(c) { xhr.Progress = c; return this; };



            /*
                Before
            */

            xhr.onreadystatechange = function() {

                if (xhr.readyState == 2)
                try { xhr.Before.call(xhr, xhr); } catch { }
            }



            /*
                Progress
            */

            xhr.upload.onprogress = function(e) {

                try {

                    let percent = parseInt(e.loaded / e.total * 100);
                    xhr.Progress.call(xhr, percent, e.loaded, e.total);

                } catch { }
            }



            xhr.send(form);

            return xhr;
        }

        return post(new XMLHttpRequest());
    }
}

<button onclick='File.add()'>добавить файл</button>
<progress max='100' value='64'></progress>

Ответы (1 шт):

Автор решения: Doofy

Сначала отправлялась форма xhr.send(form), затем возвращался объект return xhr. Событие xhr.upload.onprogress выполнялось первым, затем readyState менялся на 2, 3 и 4.

Так как инициализация прогресса выполнялась первой, естественно объект не был найден. Было решено сменить событие и отправлять сперва объект, затем форму.

/*
    Before
*/

xhr.onloadstart = function() {

    try { xhr.Before.call(xhr, xhr); } catch { }
}

setTimeout(() => xhr.send(form));
return xhr;
→ Ссылка