承诺中的XMLHttpRequest进程事件

XMLHttpRequest Progress Events within a Promise

本文关键字:进程 事件 XMLHttpRequest 承诺      更新时间:2023-09-26

我很难找到任何解决方案来跟踪Promise内部的XMLHttpRequest对象的上传进度事件。

下面是我用来创建异步请求的代码示例:

var request = function(method, url, data) {
  return new Promise(function(resolve, reject) {
    xhr.open(method, url, true);
    xhr.onload = resolve;
    xhr.onerror = reject;
    xhr.send(data);
  });
};

我想要这样的东西:

  var r = request('POST', '/upload', data)
    .then(() => {
      console.log('completed');
    });
  r.upload.addEventListener('progress', (e) => {
    console.log('ProgressEvent: ', e);
  });

我正在尝试使用到目前为止工作良好的香草JavaScript来做到这一点,但我想找出一种干净的方法来做到这一点,而不使用任何第三方库

对于旧的浏览器,你可以使用ES6类来扩展Promise构造函数,并在上面添加你自己的API。

下面是一个基本的例子,将onReadyStateChange事件处理程序添加到Promise AJAX包装器。

'use strict';
const _onReadyStateChange = Symbol('onReadyStateChange');
class PromiseAJAX extends Promise {
    constructor(func) {
        let promise;
        super((resolve, reject) => {
            func(resolve, reject, function(event) {
                // Constructor will not finish before readyState 1 event.
                // That means we will not have access to promise in time.
                // Could use a setTimeot of 0 if desired to capture.
                let onReadyStateChange;
                if (promise && (onReadyStateChange = promise.onReadyStateChange)) {
                    onReadyStateChange(event);
                }
            });
        });
        promise = this;
        this[_onReadyStateChange] = undefined;
    }
    get onReadyStateChange() {
        return this[_onReadyStateChange];
    }
    set onReadyStateChange(value) {
        this[_onReadyStateChange] = value;
    }
}
////////////////////////////////////////////////////////////////////////////////
let pajax = new PromiseAJAX(function(resolve, reject, readyStateChange) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = readyStateChange;
    xhr.onload = resolve;
    xhr.onerror = reject;
    xhr.open('GET', 'https://crossorigin.me/https://www.google.com/humans.txt', true);
    xhr.send();
});
pajax.then(function(value) {
    console.log(value.target.responseText);
});
pajax.catch(function(reason) {
    console.log(reason);
});
pajax.onReadyStateChange = function(event) {
    console.log('readyState: ' + event.target.readyState);
};

这不是完全完美的,但应该为您提供扩展Promise的基础,如果需要的话。

不幸的是,基本承诺没有一种方式来表示任何类型的进度。他们只有通过/不及格,只能发送一个结果。您可以将它们视为延迟的函数返回,而不是回调。您可能需要从函数中接受进度回调,并将该信息通过备用路由发送出去。如果你使用承诺库,它们中的一些确实有一个进度回调选项(例如https://github.com/kriskowal/q搜索"进度通知")