Giter Site home page Giter Site logo

lfscamargo / files-heavylifting-react Goto Github PK

View Code? Open in Web Editor NEW
16.0 2.0 1.0 37 KB

Web Workers Implementation, for heavy file splitting and uploading

JavaScript 5.69% HTML 5.33% CSS 26.21% TypeScript 62.76%
react typescript-react webworkers workers

files-heavylifting-react's Introduction

Files HeavyLifting Processing

Its a simple implementation of webworkers to handle heavy lifting processing in the browser, sometimes we need to process a lot of data in the browser and we don't want to block the UI, so we can use webworkers to handle this task.

Main Thread

  • The main thread is the thread that runs the JavaScript code that you write.
  • The main thread is also called the UI thread because it is responsible for updating the DOM.

Worker Thread

  • Worker threads are threads that run JavaScript code in the background. And that we normally execute heavy lifting processing in the worker thread and send a event back to the main thread to update the UI.

Running the project

pnpm install
pnpm dev

Project Structure

- src/
  - App.tsx (main component that will call the worker thread)
  - types/
    - worker.ts (types for the worker)
    - file.ts
  - workers/
    - file.ts (worker)
  - hooks/
    - useFileWorker.ts (hook to use the worker and control the instance of the worker)

Worker

import { FileWorkerEventType, FileWorkerMessage } from "../types";

self.addEventListener("message", async (event: FileWorkerEventType) => {
  const { chunkSize } = event.data.input;

  switch (event.data.type) {
    case "single_file":
      try {
        const { file } = event.data.input;

        const chunks: Blob[] = [];

        for (let i = 0; i <= file.size; i += chunkSize) {
          const chunk = file.slice(i, i + chunkSize);
          chunks.push(chunk);
        }

        console.log(chunks);

        self.postMessage({
          type: "done",
          payload: {
            progress: 100,
            chunks
          }
        } as FileWorkerMessage);
      } catch (error) {
        self.postMessage({
          type: "error",
          payload: {
            error
          }
        } as FileWorkerMessage);
      }
      break;

    default:
      break;
  }
});

export {};
  • The worker will receive a file from the main thread and will split the file into chunks and send back to the main thread a array of chunks.

Hooks

import { useCallback, useMemo } from "react";
import { FileWorkerInput, FileWorkerMessage } from "../types";

export function useFilesWorker() {
  const worker = useMemo(
    () =>
      new Worker(new URL("../workers/file.ts", import.meta.url), {
        type: "module"
      }),
    []
  );

  const splitIntoChunks = useCallback(
    (file: File, chunkSize = 1024) => {
      return new Promise<Blob[]>((resolve, reject) => {
        worker.postMessage({
          type: "single_file",
          input: {
            file,
            chunkSize
          }
        } as FileWorkerInput);

        worker.addEventListener(
          "message",
          (event: MessageEvent<FileWorkerMessage>) => {
            switch (event.data.type) {
              case "done":
                console.log(event.data);
                resolve(event.data.payload.chunks);
                break;

              case "error":
                console.log(event.data);
                reject(event.data.payload.error);
                break;
              default:
                break;
            }
          },
          {
            once: true
          }
        );
      });
    },
    [worker]
  );

  return {
    worker,
    handlers: {
      splitIntoChunks
    }
  };
}
  • The hook will create a instance of the worker and will return a function to split the file into chunks.

App

import "./App.css";
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import { useFilesWorker } from "./hooks/useFileWorker";

function App() {
  const { handlers } = useFilesWorker();
  const [isSending, setSending] = useState(false);

  const splitIntoChunks = async (file: File) => {
    try {
      if (!file || isSending) return;
      setSending(true);
      const chunks = await handlers.splitIntoChunks(file, 1024);
      console.log("Chunks", chunks);
    } catch (error) {
      console.log(error);
    } finally {
      setSending(false);
    }
  };

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <input
          type="file"
          disabled={isSending}
          onChange={(e) => splitIntoChunks(e.target.files![0] as File)}
        />
        <p>{isSending ? "Processing File" : "Send Another File"}</p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  );
}

export default App;
  • The main component will call the hook and will call the function to split the file into chunks.

files-heavylifting-react's People

Contributors

lfscamargo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

1mateus

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.