最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript使用多線程實現一個大文件上傳

 更新時間:2024年11月05日 11:11:56   作者:Lemonjing  
這篇文章主要為大家詳細介紹了JavaScript使用多線程實現一個大文件上傳的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下

開發(fā)者: JavaScript,你給我把這十個G的文件處理一下,給文件分分片,每個分片給我計算一個hash值,服務端拿到hash值就可以知道這個分片已經上傳過了(斷點續(xù)傳),還有整個文件也計算一下,說不定整個文件都上傳過了(重復文件不用多次上傳)。

JavaScript: 這活你給我干是吧,我直接給你瀏覽器卡死。

const CHUNK_SIZE = 5 * 1024 * 1024; // 分片大小
async function getFile(file) {
  const result = [];
  const chunkLength = Math.ceil(file.size / CHUNK_SIZE);
  for (let i = 0; i < chunkLength; i++) {
    const chunk = await getChunk(file, CHUNK_SIZE, i);
    result.push(chunk);
  }
}

function getChunk(file, size, index) {
  return new Promise((resolve, reject) => {
    const start = index * size;
    const end = start + size;
    const chunkFile = file.slice(start, end);
    const fr = new FileReader();
    fr.onload = function(e) {
      const arrBuffer = e.target.result;
      const hash = SparkMD5.ArrayBuffer.hash(arrBuffer);
      resolve({
        start,
        end,
        chunkFile,
        index,
        hash
      })
    }
    fr.readAsArrayBuffer(chunkFile);
  })
}

JavaScript:開心不,不動了吧,讓你不聽我的,還嘚瑟不?開發(fā)者: 不是吧,阿sir,你來真的???

為什么JavaScript要撂挑子呢?

在瀏覽器的事件循環(huán)中,我們知道不同的線程會處理不同的任務,默認的線程比如 http 線程、io 線程等等。

如果我們想在瀏覽器中進行復雜的計算,如果都在主線程操作,那么主線程就會阻塞,導致頁面的響應不及時,造成卡頓。

有沒有什么辦法可以讓主線程和計算線程分離呢?

答案當然是webworker啦

webworker 允許我們開啟一個單獨的線程,去處理一些復雜的計算任務,當計算完成之后,通過回調的形式通知主線程,主線程只要處理拿到計算結果之后的邏輯就可以了。

那我們就來學學怎么使用

1. 創(chuàng)建一個 worker 實例

const worker = new Worker("./worker.js");
// 如果需要指定worker的js可以使用ESM,可以添加type參數
const worker = new Worker("./worker.js", { type: "module" });

2. 告訴 worker 開始工作

這個worker是剛剛創(chuàng)建時候的wokerjs里面的代碼哦

worker.postMessage("開始工作");

3. 監(jiān)聽 worker 的消息

worker.onmessage = (e) => {
  // 內部worker執(zhí)行完了,或者執(zhí)行到某個節(jié)點了
};

4. 關閉 worker

worker.terminate();

5. worker 內部如何與主線程通信

self.onmessage = (e) => {
  // 收到了外部worker的消息
  // 復雜邏輯
  self.postMessage("計算完成");
};

讓worker代替主線程執(zhí)行復雜計算

const CHUNK_SIZE = 5 * 1024 * 1024; // 分片大小
const worker = new Worker('./worker.js', {
  type: 'module'
});

fileDom.onchange = function(e) {
  const file = e.target.files[0];
  worker.postMessage([file, CHUNK_SIZE]);
}
// worker.js
self.onmessage = async (e) => {
  const [file, CHUNK_SIZE] = e.data;
  const result = [];
  const chunkLength = Math.ceil(file.size / CHUNK_SIZE);
  for (let i = 0; i < chunkLength; i++) {
    const chunk = await getChunk(file, CHUNK_SIZE, i);
    result.push(chunk);
  }
  // 處理完成了
  self.postMessage(result);
}

function getChunk(file, size, index) {
  return new Promise((resolve, reject) => {
    const start = index * size;
    const end = start + size;
    const chunkFile = file.slice(start, end);
    const fr = new FileReader();
    fr.onload = function(e) {
      const arrBuffer = e.target.result;
      const hash = SparkMD5.ArrayBuffer.hash(arrBuffer);
      resolve({
        start,
        end,
        chunkFile,
        index,
        hash
      })
    }
    fr.readAsArrayBuffer(chunkFile);
  })
}

線程嘛,開了一個就有倆,仨。。。

// 直接開啟四個worker
const MAX_WORKER_NUM = 4;
const workers = new Array(MAX_WORKER_NUM).fill(0).map(() => new Worker('./worker.js', { type: 'module' }));
const wholeFileWorker = new Worker('./hashWholeFile.js', { type: 'module' });
let finishedCount = 0;
fileDom.onchange = function(e) {
  const file = e.target.files[0];
  // 計算一下一共有多少個分片
  const chunkLength = Math.ceil(file.size / CHUNK_SIZE);
  // 每一個worker要完成多少分片
  // 假如有99個分片,那第一個worker要處理1-25,第二個26-50,第三個51-75,第四個76-99
  // 我們是程序員,所以每一個index都要-1
  const workerSize = Math.ceil(chunkLength / MAX_WORKER_NUM);
  for(let i = 0; i < MAX_WORKER_NUM; i++) {
    const worker = workers[i];
    // 幫worker計算好分片任務的起始位置和結束位置
    const startIndex = i * workerSize;
    const endIndex = Math.min(start + workerSize, chunkLength);
    worker.postMessage([file, CHUNK_SIZE, startIndex, endIndex]);
    worker.onmessage = (e) => {
      finishedCount++;
      worker.terminate();
      // 計算完一部分的hash就可以開始上傳了,每一個返回結果里面有index,可以告訴后端傳遞的是哪個分片,信息已經足夠了
      
    }
  }
  // 前面先計算分片的hash,有分片計算好的hash就可以直接開始上傳了
  wholeFileWorker.postMessage([file]);
  wholeFileWorker.onmessage = (e) => {
    // 最后處理整個文件的hash
    // 這樣整體效果就是,用戶選擇文件之后,可以快速的開始上傳進度條,
    // 如果是之前上傳了部分,并且開始上傳的分片之前已經上傳好了,那么可以快速跳過這些分片,直接上傳剩下的分片
    // 如果之前整個文件都上傳了,那么進度條會從很少的地方直接跳到100%
  }

}
// worker.js
import "./md5.min.js"
self.onmessage = async (e) => {
  const [file, CHUNK_SIZE, startIndex, endIndex] = e.data;
  const result = [];
  for (let i = startIndex; i < endIndex; i++) {
    const chunk = await getChunk(file, CHUNK_SIZE, i);
    result.push(chunk);
  }
  // 處理完成了
  self.postMessage(result);
}

function getChunk(file, size, index) {
  return new Promise((resolve, reject) => {
    const start = index * size;
    const end = start + size;
    const chunkFile = file.slice(start, end);
    const fr = new FileReader();
    fr.onload = function(e) {
      const arrBuffer = e.target.result;
      const hash = SparkMD5.ArrayBuffer.hash(arrBuffer);
      resolve({
        start,
        end,
        chunkFile,
        index,
        hash
      })
    }
    fr.readAsArrayBuffer(chunkFile);
  })
}

// hashWholeFile.js
import "./md5.min.js"
self.onmessage = (e) => {
  const [file] = e.data;
  const hash = SparkMD5.ArrayBuffer.hash(file);
  self.postMessage(hash);
}

到此這篇關于JavaScript使用多線程實現一個大文件上傳的文章就介紹到這了,更多相關JavaScript大文件上傳內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 學習JavaScript編程語言的8張思維導圖分享

    學習JavaScript編程語言的8張思維導圖分享

    這篇文章主要介紹了學習JavaScript編程語言的8張思維導圖分享,本文給出了javascript變量、javascript運算符、javascript數組、javascript流程語句、javascript字符串函數、javascript函數基礎、javascript基礎DOM操作、javascript正則表達式的思維導圖,需要的可以參考下
    2015-03-03
  • 前端圖片加載錯誤的多種原因分析

    前端圖片加載錯誤的多種原因分析

    在瀏覽網頁或使用應用程序時,圖片加載失敗是一個常見的問題,下面這篇文章主要介紹了前端圖片加載錯誤的多種原因分析的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-03-03
  • 微信公眾平臺API錯誤代碼41002的問題解決辦法

    微信公眾平臺API錯誤代碼41002的問題解決辦法

    今天在研究微信公眾號接口問題,下面這篇文章主要給大家介紹了關于微信公眾平臺API錯誤代碼41002問題的解決辦法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-09-09
  • 微信小程序基于本地緩存實現點贊功能的方法

    微信小程序基于本地緩存實現點贊功能的方法

    這篇文章主要介紹了微信小程序基于本地緩存實現點贊功能的方法,涉及微信小程序界面布局、事件響應及緩存操作等相關實現技巧,需要的朋友可以參考下
    2017-12-12
  • 使用?JS?判斷用戶是否處于活躍狀態(tài)的案例詳解

    使用?JS?判斷用戶是否處于活躍狀態(tài)的案例詳解

    這篇文章主要介紹了如何使用?JS?判斷用戶是否處于活躍狀態(tài),案例演示了如何獲取用戶活躍狀態(tài),時間閾值定為5秒,超出該閾值沒有操作表示非活躍,否則屬于正在活躍中,需要的朋友可以參考下
    2024-05-05
  • 前端如何寫一個大文件上傳組件詳細步驟

    前端如何寫一個大文件上傳組件詳細步驟

    在現代Web應用中,大文件上傳是一個常見的需求,尤其是在云存儲、社交媒體和協(xié)作平臺等領域,這篇文章主要介紹了前端如何寫一個大文件上傳組件詳細步驟,需要的朋友可以參考下
    2025-04-04
  • javascript清空table表格的方法

    javascript清空table表格的方法

    這篇文章主要介紹了javascript清空table表格的方法,涉及javascript操作table表格的技巧,需要的朋友可以參考下
    2015-05-05
  • JavaScript去除文件名稱中的后綴名的多種方法

    JavaScript去除文件名稱中的后綴名的多種方法

    本文介紹了JavaScript中去除文件名后綴名的四種方法,并推薦使用substring()和lastIndexOf()方法,因為它簡潔易懂,性能較好,并能處理特殊情況,需要的朋友可以參考下
    2025-12-12
  • 原生js實現對Ajax的封裝(仿jquery)

    原生js實現對Ajax的封裝(仿jquery)

    這篇文章主要為大家詳細介紹了原生js實現對Ajax的封裝,模仿jquery,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • JSONP獲取Twitter和Facebook文章數的具體步驟

    JSONP獲取Twitter和Facebook文章數的具體步驟

    這篇文章主要介紹了JSONP獲取Twitter和Facebook文章數的方法,需要的朋友可以參考下
    2014-02-02

最新評論

沅陵县| 高州市| 电白县| 宾川县| 遂溪县| 陕西省| 都安| 神池县| 达孜县| 叙永县| 毕节市| 台南市| 伊宁市| 华池县| 泾阳县| 沁阳市| 外汇| 富平县| 瑞安市| 五河县| 蚌埠市| 高雄县| 铜鼓县| 长泰县| 徐汇区| 旺苍县| 徐汇区| 云霄县| 成都市| 丽水市| 长顺县| 博乐市| 五原县| 全椒县| 理塘县| 九龙坡区| 金寨县| 新兴县| 荔波县| 南岸区| 桑植县|