88 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
 | 
						|
export const streamChunk = function* (chunk, chunkSize) {
 | 
						|
  let len = chunk.byteLength;
 | 
						|
 | 
						|
  if (!chunkSize || len < chunkSize) {
 | 
						|
    yield chunk;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  let pos = 0;
 | 
						|
  let end;
 | 
						|
 | 
						|
  while (pos < len) {
 | 
						|
    end = pos + chunkSize;
 | 
						|
    yield chunk.slice(pos, end);
 | 
						|
    pos = end;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export const readBytes = async function* (iterable, chunkSize) {
 | 
						|
  for await (const chunk of readStream(iterable)) {
 | 
						|
    yield* streamChunk(chunk, chunkSize);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const readStream = async function* (stream) {
 | 
						|
  if (stream[Symbol.asyncIterator]) {
 | 
						|
    yield* stream;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const reader = stream.getReader();
 | 
						|
  try {
 | 
						|
    for (;;) {
 | 
						|
      const {done, value} = await reader.read();
 | 
						|
      if (done) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      yield value;
 | 
						|
    }
 | 
						|
  } finally {
 | 
						|
    await reader.cancel();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export const trackStream = (stream, chunkSize, onProgress, onFinish) => {
 | 
						|
  const iterator = readBytes(stream, chunkSize);
 | 
						|
 | 
						|
  let bytes = 0;
 | 
						|
  let done;
 | 
						|
  let _onFinish = (e) => {
 | 
						|
    if (!done) {
 | 
						|
      done = true;
 | 
						|
      onFinish && onFinish(e);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return new ReadableStream({
 | 
						|
    async pull(controller) {
 | 
						|
      try {
 | 
						|
        const {done, value} = await iterator.next();
 | 
						|
 | 
						|
        if (done) {
 | 
						|
         _onFinish();
 | 
						|
          controller.close();
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        let len = value.byteLength;
 | 
						|
        if (onProgress) {
 | 
						|
          let loadedBytes = bytes += len;
 | 
						|
          onProgress(loadedBytes);
 | 
						|
        }
 | 
						|
        controller.enqueue(new Uint8Array(value));
 | 
						|
      } catch (err) {
 | 
						|
        _onFinish(err);
 | 
						|
        throw err;
 | 
						|
      }
 | 
						|
    },
 | 
						|
    cancel(reason) {
 | 
						|
      _onFinish(reason);
 | 
						|
      return iterator.return();
 | 
						|
    }
 | 
						|
  }, {
 | 
						|
    highWaterMark: 2
 | 
						|
  })
 | 
						|
}
 |