【问题标题】:XMLHttpRequest Progress Events within a PromisePromise 中的 XMLHttpRequest 进度事件
【发布时间】:2017-01-21 07:13:48
【问题描述】:

我无法找到任何解决方案来跟踪 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);
  });

我正在尝试使用迄今为止运行良好的 vanilla JavaScript 来做到这一点,但我想找到一种不使用任何第三方库的干净方法。

【问题讨论】:

标签: javascript xmlhttprequest promise


【解决方案1】:

对于旧版浏览器使用 some caveats,您可以使用 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 的基础知识。

【讨论】:

  • 继承在 ES5 中也有效。它只是看起来不像这样。 (顺便说一句,这仍然不能处理进度事件。)
【解决方案2】:

不幸的是,基础承诺无法代表任何进展。它们只有通过/失败,并且只能发送一个结果。您可以将它们更多地视为延迟函数返回而不是回调。您可能需要从您的函数中接受进度回调并将该信息发送到备用路线。如果您使用 Promise 库,其中一些确实有进度回调选项(例如 https://github.com/kriskowal/q 搜索“进度通知”)

【讨论】:

  • 是的,我搜索的越多,我就越需要走那条路。
猜你喜欢
  • 2016-08-12
  • 2021-07-31
  • 2012-02-07
  • 2014-05-15
  • 2011-12-23
  • 2013-06-21
  • 2016-06-29
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多