日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解JavaScript進度管理

瀏覽:30日期:2023-06-05 11:45:49
前言

我們寫程序的時候會經常遇到顯示進度的需求,如加載進度、上傳進度等。最常見的實現方式是通過記錄已完成數量(loadedCount)和總數量(totalCount),然后算一下就能得到進度了。這種方式簡單粗暴,容易實現,但不好擴展,必須有個地方維護所有loadedCount和totalCount。本文將會基于上述實現方式,實現一種更容易擴展的進度管理方式。

問題

筆者在寫 WebGL 應用,在應用預加載階段需要計算加載進度。加載的內容包括:模型資源、貼圖資源、腳本資源等。其中模型資源中又會包含材質資源,材質資源里面又會包含貼圖資源。畫圖來表示的話就是如下的結構:

+-------------------------------------------------------------+| || resources || || +----------+ +-----------------+ +-----------------+ || | script1 | | model1 | | model2 | || +----------+ | | | | || | -------------+ | | -------------+ | || +----------+ | |model1.json | | | |model2.json | | || | script2 | | +------------+ | | +------------+ | || +----------+ | | | | || | +------------+ | | +------------+ | || +----------+ | | material1 | | | | material1 | | || | texture1 | | | +--------+ | | | | +--------+ | | || +----------+ | | |texture1| | | | | |texture1| | | || | | +--------+ | | | | +--------+ | | || +----------+ | | +--------+ | | | | +--------+ | | || | texture2 | | | |texture2| | | | | |texture2| | | || +----------+ | | +--------+ | | | | +--------+ | | || | +------------+ | | +------------+ | || | | | | || | +------------+ | | +------------+ | || | | material2 | | | | material2 | | || | +------------+ | | +------------+ | || +-----------------+ +-----------------+ || |+-------------------------------------------------------------+

這里有個前提:當加載某個資源的時候,必須保證這個資源及它引用的資源全部加載完成后,才能算加載完成。基于這個前提,我們已經實現了一個onProgress接口,這個接口返回的進度是已經包含了子資源的加載進度的了。翻譯成代碼就是:

class Asset { load(onProgress) {return new Promise((resolve) => { if (typeof onProgress !== ’function’) {onProgress = (_p) => { }; } let loadedCount = 0; let totalCount = 10; // NOTE: just for demo let onLoaded = () => {loadedCount++;onProgress(loadedCount / totalCont);if (loadedCount === totalCount) resolve(); }; Promise.all(this.refAssets.map(asset => asset.load().then(onLoaded)) );}); }}

既然有了這個接口,如果沿用全局維護loadedCount和totalCount的形式的話,處理起來其實挺麻煩的。本文接下來要介紹的,就是一種變通的做法。

原理

基本思想就是分而治之。把一個大任務拆分成多個小任務,然后分別計算所有小任務的進度,最后再把所有小任務的進度歸并起來得到總進度。如下圖表示:

+--------------------------------------------------------------------+||||| total progress |||| +---------+---------+----------+----------+--------+--------+ || | script1 | script2 | texture1 | texture2 | model1 | model2 | || | (0~1) | (0~1) | (0~1) | (0~1) | (0~1) | (0~1) | || +---------+---------+----------+----------+--------+--------+ |||| model1 || +-------------+-----------------------+-----------+ || | model1.json | material1| material2 | || | (0~1) |(0~1) | (0~1) | || +------------------------+------------------------+ || | texture1 | texture2 | || | (0~1) | (0~1) | || +----------+------------+ |||| model2 || +-------------+-----------------------+-----------+ || | model2.json | material1| material2 | || | (0~1) |(0~1) | (0~1) | || +------------------------+------------------------+ || | texture1 | texture2 | || | (0~1) | (0~1) | || +----------+------------+ |||+--------------------------------------------------------------------+

基于這個原理去實現進度,實現方式就是通過一個列表去保存所有資源當前的加載進度,然后每次觸發onProgress的時候,執行一次歸并操作,計算總進度。

var progresses = [ 0, // script1, 0, // script2, 0, // texture1, 0, // texture2, 0, // model1, 0, // model2];function onProgress(p) { // TODO: progresses[??] = p; return progresses.reduce((a, b) => a + b, 0) / progresses.length;}

但這里面有個難點,當觸發onProgress回調的時候,如何知道應該更新列表中的哪一項呢?利用JavaScript的閉包特性,我們可以很容易實現這一功能。

var progresses = [];function add() { progresses.push(0); var index = progresses.length - 1; return function onProgress(p) {progresses[index] = p;reduce(); };}function reduce() { return progresses.reduce((a, b) => a + b, 0) / progresses.length;}

利用閉包保留資源的索引,當觸發onProgress的時候,就能根據索引去更新列表中對應項的進度了。最后歸并的時候就能計算出正確的進度了。剩下的事情就是整合我們所有的代碼,然后對其進行測試了

測試

我們可以用下面的代碼來模擬一下整個加載過程:

class Asset { constructor(totalCount) {this.loadedCount = 0;this.totalCount = totalCount;this.timerId = -1; } load(onProgress) {if (typeof onProgress !== ’function’) { onProgress = (_p) => { };}return new Promise((resolve) => { this.timerId = setInterval(() => {this.loadedCount++;onProgress(this.loadedCount / this.totalCount);if (this.loadedCount === this.totalCount) { clearInterval(this.timerId); resolve();} }, 1000);}); }}class Progress { constructor(onProgress) {this.onProgress = onProgress;this._list = []; } add() {this._list.push(0);const index = this._list.length - 1;return (p) => { this._list[index] = p; this.reduce();}; } reduce() {const p = Math.min(1, this._list.reduce((a, b) => a + b, 0) / this._list.length);this.onProgress(p); }}const p = new Progress(console.log);const asset1 = new Asset(1);const asset2 = new Asset(2);const asset3 = new Asset(3);const asset4 = new Asset(4);const asset5 = new Asset(5);Promise.all([ asset1.load(p.add()), asset2.load(p.add()), asset3.load(p.add()), asset4.load(p.add()), asset5.load(p.add()),]).then(() => console.log(’all resources loaded’));/** 輸出 Promise { <state>: 'pending' } 0.2 0.3 0.36666666666666664 0.41666666666666663 0.45666666666666667 0.5566666666666668 0.6233333333333333 0.6733333333333333 0.7133333333333333 0.78 0.8300000000000001 0.8699999999999999 0.9199999999999999 0.96 1 all resources loaded */

這種方式的優點是能避開全局管理loadedCount和totalCount,把這部分工作交回資源內部管理,它要做的只是對大任務進行歸并計算。

缺點也很明顯,需要對onProgress接口進行一次統一。在已有項目中推進難度很大,所以比較適合新項目或者小項目去實踐。

以上就是JavaScript進度管理的詳細內容,更多關于JavaScript進度管理的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
激情视频一区二区三区| 欧美福利专区| 日韩午夜av| 日韩一区二区免费看| 免费高潮视频95在线观看网站| 国产乱人伦精品一区| 久久不见久久见免费视频7| 欧美日本二区| 精品深夜福利视频| 精品国产一区二| 国产v日韩v欧美v| 久久婷婷激情| 一本一本久久| 欧美伊人久久| 狠狠躁少妇一区二区三区| 久久亚洲国产| 一区二区三区四区在线观看国产日韩| 视频一区日韩精品| 久久午夜影院| 国产亚洲欧洲| 国产麻豆一区二区三区| 欧洲av不卡| 亚洲另类av| 久热re这里精品视频在线6| 视频一区二区中文字幕| 国产日韩精品视频一区二区三区| 亚洲天堂av影院| 日韩在线成人| 私拍精品福利视频在线一区| 三级欧美在线一区| 精品国产精品国产偷麻豆 | 丝袜诱惑制服诱惑色一区在线观看 | 精品国产一区二区三区噜噜噜| 婷婷激情久久| 国产精品xxx| 亚洲一区二区三区高清不卡| 精品网站aaa| 日韩在线网址| 亚洲激情五月| 精品国产网站| 欧美日韩一区自拍| 欧美不卡高清| 精品成人18| 日韩三级一区| 每日更新成人在线视频| 久久久久国产精品一区二区| 欧美精品二区| 欧美性www| 日韩福利视频导航| 免费不卡在线视频| 伊人精品视频| 国产一区久久| 成人看片网站| 日本免费一区二区三区四区| 国产福利一区二区三区在线播放| 久久国产精品亚洲77777| 91精品蜜臀一区二区三区在线| 国产精品一区二区三区av麻| 免费在线观看精品| 快she精品国产999| 视频一区欧美日韩| 亚洲美女91| 欧美亚洲免费| 欧美日韩伊人| 久久精品日韩欧美| 精品国产欧美日韩一区二区三区| 国产精品久久久久久久久久白浆 | 夜夜精品视频| 99综合视频| 国产精品毛片在线看| 亚洲视频www| 亚洲精品日本| 日韩av一区二区三区| 国产精品手机在线播放| 精品久久久网| 久久精品国产大片免费观看| 久久高清免费| 午夜天堂精品久久久久| 日韩高清在线观看一区二区| 国产乱码精品一区二区三区四区 | 国产精品日本| 日韩欧乱色一区二区三区在线| 日本va欧美va精品| 成人精品动漫一区二区三区| 久久一区二区三区喷水| 国产毛片久久| 日本电影久久久| 麻豆视频久久| 午夜国产精品视频| 日韩av在线免费观看不卡| 在线天堂资源www在线污| 蜜臀久久99精品久久久久久9 | 国产精品主播在线观看| 热三久草你在线| 亚洲精品欧美| 国产传媒av在线| 亚洲一区网站| 国产美女精品视频免费播放软件| 播放一区二区| 国产亚洲一区二区三区啪| 久久久成人网| 久久一区欧美| 日本免费新一区视频| 91九色精品| 国产一区二区三区亚洲综合| 四虎在线精品| 亚洲二区三区不卡| a天堂资源在线| 国产精品欧美三级在线观看| 鲁大师影院一区二区三区| 欧美成人a交片免费看| 国产精品免费精品自在线观看| 不卡在线一区| 久久精品99久久无色码中文字幕| 麻豆传媒一区二区三区| 天堂av在线一区| 一区福利视频| 国产精品女主播一区二区三区| 午夜欧美巨大性欧美巨大| 免费在线日韩av| 国产亚洲高清在线观看| 亚洲精品在线二区| 久久亚洲不卡| 日本中文字幕视频一区| 蜜臀久久99精品久久久久宅男| 欧美日韩国产精品一区二区亚洲| 欧美freesex黑人又粗又大| 国产精品久久久久久久久久妞妞 | 麻豆免费精品视频| 美女精品视频在线| 欧美aaaaaa午夜精品| 国产精品调教视频| 国产aⅴ精品一区二区四区| 久久影院一区二区三区| 久久国产三级| 国产精品夜夜夜| 精品久久中文| 日韩福利一区| 亚洲欧美日本日韩| 亚洲免费福利一区| 欧美日一区二区在线观看| 人人爱人人干婷婷丁香亚洲| 国产日韩中文在线中文字幕| 国产精品多人| 日韩伦理一区| 蜜桃av一区二区三区电影| 日韩成人午夜精品| 久久久久亚洲精品中文字幕| 99久久亚洲精品| 免费在线观看视频一区| 国产丝袜一区| 欧美福利专区| 国产美女久久| 欧美1区免费| 国产精品亚洲欧美| 99久久精品费精品国产| 日韩高清不卡一区二区| 国产成人精品亚洲日本在线观看| 国产婷婷精品| 久久精品日韩欧美| 首页欧美精品中文字幕| 精品国产黄a∨片高清在线| 日韩午夜av| 91日韩在线| 综合亚洲视频| 欧洲亚洲一区二区三区| 天堂精品久久久久| 久久中文字幕二区| 国产精品nxnn| 日韩欧美久久| 精品一区在线| 国产传媒av在线| 国产欧美一区二区精品久久久| 欧美特黄一区| 高清av一区二区三区| 国产欧美日韩精品高清二区综合区 | 日韩av在线播放中文字幕| 不卡在线一区二区| 精品国产午夜肉伦伦影院| 日韩不卡一区二区| 国产精品普通话对白| 日韩在线看片| 福利一区二区三区视频在线观看| 亚洲欧美日本国产| 亚洲欧美日本视频在线观看| 久久国产电影| 日韩深夜视频| 日韩综合一区| 久久久久久久欧美精品| 国产精品对白| 久久精品福利| 欧美天堂一区| 免费一区二区三区在线视频| 亚洲免费毛片| 日韩一区二区三区高清在线观看 | 今天的高清视频免费播放成人| 成人在线视频中文字幕| 国产精品高清一区二区| 免费看一区二区三区| 国内一区二区三区|