Подтвердить что ты не робот

Загрузить индикаторы прогресса для извлечения?

Я изо всех сил пытаюсь найти документацию или примеры реализации индикатора прогресса загрузки, используя fetch.

Это единственная ссылка, которую я нашел до сих пор, в которой говорится:

События прогресса - это функция высокого уровня, которая пока не будет полученна в выборке. Вы можете создать свой собственный, посмотрев заголовок Content-Length и используя сквозной поток для отслеживания полученных байтов.

Это означает, что вы можете явно обрабатывать ответы без Content-Length по-разному. И, конечно, даже если Content-Length, это может быть ложью. С потоками вы можете справиться с этой ложью, как хотите.

Как бы я написал "передаваемый поток для отслеживания байтов"? Если это имеет какое-то значение, я пытаюсь сделать это, чтобы загрузить изображения с изображения в браузере на Cloudinary.

ПРИМЕЧАНИЕ. Я не, интересующийся облачной JS-библиотекой, поскольку это зависит от jQuery и моего приложение не работает. Меня интересует только обработка потока, необходимая для этого, с помощью встроенного javascript и Github fetch polyfill.


https://fetch.spec.whatwg.org/#fetch-api

4b9b3361

Ответ 1

Потоки начинают приземляться в веб-платформу (https://jakearchibald.com/2016/streams-ftw/), но это еще рано.

Вскоре вы сможете предоставить поток как тело запроса, но открытым вопросом является вопрос о том, связано ли потребление этого потока с загруженными байтами.

Частные перенаправления могут привести к повторной передаче данных в новое местоположение, но потоки не могут "перезапускаться". Мы можем исправить это, превратив тело в обратный вызов, который можно вызвать несколько раз, но мы должны быть уверены, что разоблачение количества переадресаций не является утечкой безопасности, так как это будет первый раз на платформе JS, обнаружить это.

Некоторые спрашивают, имеет ли смысл связывать потребление потока с загруженными байтами.

Короче говоря: это пока невозможно, но в будущем это будет обрабатываться либо потоками, либо каким-то обратным вызовом более высокого уровня, переданным в fetch().

Ответ 2

Я не думаю, что это возможно. В проекте говорится:

в настоящее время отсутствует [по сравнению с XHR], когда дело доходит до прогрессирования запроса


(старый ответ):
Первый пример в главе Fetch API дает некоторое представление о том, как:

Если вы хотите получать данные тела постепенно:

function consume(reader) {
  var total = 0
  return new Promise((resolve, reject) => {
    function pump() {
      reader.read().then(({done, value}) => {
        if (done) {
          resolve()
          return
        }
        total += value.byteLength
        log(`received ${value.byteLength} bytes (${total} bytes in total)`)
        pump()
      }).catch(reject)
    }
    pump()
  })
}

fetch("/music/pk/altes-kamuffel.flac")
  .then(res => consume(res.body.getReader()))
  .then(() => log("consumed the entire body without keeping the whole thing in memory!"))
  .catch(e => log("something went wrong: " + e))

Помимо использования Promise конструктора antipattern, вы можете видеть, что response.body - это поток, из которого вы можете читать байты по байту с помощью Reader, и вы можете запустить событие или сделать все, что вам нравится (например, зарегистрировать прогресс) для каждого из них.

Однако Streams spec не выглядит вполне законченным, и я понятия не имею, работает ли это уже в любой реализации выборки.

Ответ 3

Так как ни один из ответов не решает проблему.

Просто для реализации вы можете определить скорость загрузки с небольшим начальным фрагментом известного размера и время загрузки можно рассчитать с помощью Content-Length/загрузки скорость. Вы можете использовать это время как оценку.

Ответ 4

Возможным обходным путем было бы использовать конструктор new Request(), а затем проверить атрибут Request.bodyUsed Boolean

Атрибуты bodyUsed getter должны возвращать true, если disturbed и false в противном случае.

чтобы определить, является ли поток distributed

Объект, реализующий mixin Body, называется disturbed, если Body не является нулевым, а его stream - disturbed.

Верните fetch() Promise из .then() с привязкой к рекурсивному .read() вызову ReadableStream, когда Request.bodyUsed равно true.

Примечание. Этот подход не считывает байты Request.body, поскольку байты передаются в конечную точку. Кроме того, загрузка может завершиться задолго до того, как любой ответ будет полностью возвращен браузеру.

const [input, progress, label] = [
  document.querySelector("input")
  , document.querySelector("progress")
  , document.querySelector("label")
];

const url = "/path/to/server/";

input.onmousedown = () => {
  label.innerHTML = "";
  progress.value = "0"
};

input.onchange = (event) => {

  const file = event.target.files[0];
  const filename = file.name;
  progress.max = file.size;

  const request = new Request(url, {
    method: "POST",
    body: file,
    cache: "no-store"
  });

  const upload = settings => fetch(settings);

  const uploadProgress = new ReadableStream({
    start(controller) {
        console.log("starting upload, request.bodyUsed:", request.bodyUsed);
        controller.enqueue(request.bodyUsed);
    },
    pull(controller) {
      if (request.bodyUsed) {
        controller.close();
      }
      controller.enqueue(request.bodyUsed);
      console.log("pull, request.bodyUsed:", request.bodyUsed);
    },
    cancel(reason) {
      console.log(reason);
    }
  });

  const [fileUpload, reader] = [
    upload(request)
    .catch(e => {
      reader.cancel();
      throw e
    })
    , uploadProgress.getReader()
  ];

  const processUploadRequest = ({value, done}) => {
    if (value || done) {
      console.log("upload complete, request.bodyUsed:", request.bodyUsed);
      // set `progress.value` to `progress.max` here 
      // if not awaiting server response
      // progress.value = progress.max;
      return reader.closed.then(() => fileUpload);
    }
    console.log("upload progress:", value);
    progress.value = +progress.value + 1;
    return reader.read().then(result => processUploadRequest(result));
  };

  reader.read().then(({value, done}) => processUploadRequest({value,done}))
  .then(response => response.text())
  .then(text => {
    console.log("response:", text);
    progress.value = progress.max;
    input.value = "";
  })
  .catch(err => console.log("upload error:", err));

}

Ответ 5

Мое решение состоит в том, чтобы использовать axios, что очень хорошо это поддерживает:

      axios.request( {
        method: "post", 
        url: "/aaa", 
        data: myData, 
        onUploadProgress: (p) => {
          console.log(p); 
          //this.setState({
            //fileprogress: p.loaded / p.total
          //})
        }


      }).then (data => {
        //this.setState({
          //fileprogress: 1.0,
        //})
      })

У меня есть пример для использования этого в реакции на github.

Ответ 6

const response = await fetch(url);
const total = Number(response.headers.get('content-length'));

const reader = response.body.getReader();
let bytesReceived = 0;
while (true) {
    const result = await reader.read();
    if (result.done) {
        console.log('Fetch complete');
        break;
    }
    bytesReceived += result.value.length;
    console.log('Received', bytesReceived, 'bytes of data so far');
}

благодаря этой ссылке: https://jakearchibald.com/2016/streams-ftw/

Ответ 7

const req = await fetch('./foo.json');
const total = Number(req.headers.get('content-length'));
let loaded = 0;
for await(const {length} of req.body.getReader()) {
  loaded = += length;
  const progress = ((loaded / total) * 100).toFixed(2); // toFixed(2) means two digits after floating point
  console.log(`${progress}%`); // or yourDiv.textContent = `${progress}%`;
}

Ответ 8

Основная часть ReadableStream < obj_response.Body > .

Пример:

let parse=_/*result*/=>{
  console.log(_)
  //...
  return /*cont?*/_.value?true:false
}

fetch('').
then(_=>( a/*!*/=_.body.getReader(), b/*!*/=z=>a.read().then(parse).then(_=>(_?b:z=>z)()), b() ))

Вы можете протестировать его на огромной странице, например https://html.spec.whatwg.org/ и https://html.spec.whatwg.org/print.pdf. CtrlShiftJ и загрузите код.

(Протестировано в Chrome.)