在一个承诺中使用XMLHttpRequest进度事件

3
我遇到了一些问题,无法找到任何解决方案来跟踪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完成这个任务,目前已经进展得很顺利,但我想找出一种不需要使用任何第三方库的干净方法来完成这个任务。


JQuery 3.x符合Promises/A+规范,其$.ajax函数支持进度事件:https://api.jquery.com/deferred.progress/ - PHP Guru
2个回答

4

使用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中也可以使用,只是看起来不太一样。(顺便说一下,这仍然无法处理进度事件。) - PHP Guru

3

很遗憾,基础的 Promise 对象不能表示任何进度。它们只有成功或失败两种状态,并且只能返回一个结果。你可以将它们视为延迟函数返回而不是回调函数。你可能需要从函数中接受一个进度回调,并通过其他途径发送该信息。如果你使用 Promise 库,其中一些库提供了进度回调选项(例如:https://github.com/kriskowal/q 搜索“进度通知”)。


是的,我搜索得越多,看起来我就必须采取那种方式。 - ZiggidyCreative

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接