Polyfill用于获取上传进度,无需流

时间:2018-12-03 14:48:18

标签: file-upload fetch

我遇到了Fetch API不支持进度的问题。我已经阅读了相关的topics并且ReadableStreams看起来不错,但是由于我们的依赖关系策略(仍然处于早期阶段,必须在许多browsers中进行填充),因此我们无法使用它。 / p>

因此,我们需要基于最近可用的API(很可能是XHR)构建的polyfill。我虽然会分享我们的实现。虽然它不是很复杂,但是可以为其他人节省一些时间。

1 个答案:

答案 0 :(得分:0)

这是我们的解决方案,该解决方案可以回溯到XHR,同时努力保持与fetch的签名接近。请注意,这里重点关注进度,省略了响应状态和响应数据。

interface OnProgress {
    (loaded: number, total: number, done: boolean): void;
}

export function fetch(url: string, { method, headers, body }, onProgress: OnProgress): Promise {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.upload.addEventListener('progress', e => onProgress(e.loaded, e.total, false));
        xhr.upload.addEventListener('loadend', _ => onProgress(undefined, undefined, true));
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4)
                resolve();
        };
        xhr.onerror = err => reject(err);
        Object.entries(headers).forEach(([name, value]) => xhr.setRequestHeader(name, value));
        xhr.send(body);
    });
}

用法示例:

import { fetch } from 'my-fetch-progress';

const formData = new FormData();
formData.append('file', file, file.name);
const onProgress = (loaded, total, done) => console.log('onProgress', loaded, total, done);

fetch('/my-upload', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ...` },
    body: formData
}, onProgress)
    .then(_ => /*...*/);