国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)/技術(shù)文章
文章詳情頁(yè)

詳解JavaScript進(jìn)度管理

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

我們寫程序的時(shí)候會(huì)經(jīng)常遇到顯示進(jìn)度的需求,如加載進(jìn)度、上傳進(jìn)度等。最常見的實(shí)現(xiàn)方式是通過(guò)記錄已完成數(shù)量(loadedCount)和總數(shù)量(totalCount),然后算一下就能得到進(jìn)度了。這種方式簡(jiǎn)單粗暴,容易實(shí)現(xiàn),但不好擴(kuò)展,必須有個(gè)地方維護(hù)所有l(wèi)oadedCount和totalCount。本文將會(huì)基于上述實(shí)現(xiàn)方式,實(shí)現(xiàn)一種更容易擴(kuò)展的進(jìn)度管理方式。

問(wèn)題

筆者在寫 WebGL 應(yīng)用,在應(yīng)用預(yù)加載階段需要計(jì)算加載進(jìn)度。加載的內(nèi)容包括:模型資源、貼圖資源、腳本資源等。其中模型資源中又會(huì)包含材質(zhì)資源,材質(zhì)資源里面又會(huì)包含貼圖資源。畫圖來(lái)表示的話就是如下的結(jié)構(gòu):

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

這里有個(gè)前提:當(dāng)加載某個(gè)資源的時(shí)候,必須保證這個(gè)資源及它引用的資源全部加載完成后,才能算加載完成?;谶@個(gè)前提,我們已經(jīng)實(shí)現(xiàn)了一個(gè)onProgress接口,這個(gè)接口返回的進(jìn)度是已經(jīng)包含了子資源的加載進(jìn)度的了。翻譯成代碼就是:

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)) );}); }}

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

原理

基本思想就是分而治之。把一個(gè)大任務(wù)拆分成多個(gè)小任務(wù),然后分別計(jì)算所有小任務(wù)的進(jìn)度,最后再把所有小任務(wù)的進(jìn)度歸并起來(lái)得到總進(jìn)度。如下圖表示:

+--------------------------------------------------------------------+||||| 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) | || +----------+------------+ |||+--------------------------------------------------------------------+

基于這個(gè)原理去實(shí)現(xiàn)進(jìn)度,實(shí)現(xiàn)方式就是通過(guò)一個(gè)列表去保存所有資源當(dāng)前的加載進(jìn)度,然后每次觸發(fā)onProgress的時(shí)候,執(zhí)行一次歸并操作,計(jì)算總進(jìn)度。

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;}

但這里面有個(gè)難點(diǎn),當(dāng)觸發(fā)onProgress回調(diào)的時(shí)候,如何知道應(yīng)該更新列表中的哪一項(xiàng)呢?利用JavaScript的閉包特性,我們可以很容易實(shí)現(xiàn)這一功能。

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;}

利用閉包保留資源的索引,當(dāng)觸發(fā)onProgress的時(shí)候,就能根據(jù)索引去更新列表中對(duì)應(yīng)項(xiàng)的進(jìn)度了。最后歸并的時(shí)候就能計(jì)算出正確的進(jìn)度了。剩下的事情就是整合我們所有的代碼,然后對(duì)其進(jìn)行測(cè)試了

測(cè)試

我們可以用下面的代碼來(lái)模擬一下整個(gè)加載過(guò)程:

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 */

這種方式的優(yōu)點(diǎn)是能避開全局管理loadedCount和totalCount,把這部分工作交回資源內(nèi)部管理,它要做的只是對(duì)大任務(wù)進(jìn)行歸并計(jì)算。

缺點(diǎn)也很明顯,需要對(duì)onProgress接口進(jìn)行一次統(tǒng)一。在已有項(xiàng)目中推進(jìn)難度很大,所以比較適合新項(xiàng)目或者小項(xiàng)目去實(shí)踐。

以上就是JavaScript進(jìn)度管理的詳細(xì)內(nèi)容,更多關(guān)于JavaScript進(jìn)度管理的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 亚洲精品自产拍在线观看 | 久久国产精品免费视频 | 亚洲视频在线观看网站 | 国产成人精品综合在线 | 丝袜黄色片 | 国产在线观看免费人成小说 | 大量真实偷拍情侣视频野战 | 伊人国产在线视频 | 国内自拍视频在线播放 | 国产欧美一区二区三区精品 | 欧美做a一级视频免费观看 欧美做爱毛片 | 久草免费在线视频 | 天堂av影院 | 亚洲黄色免费网址 | 99久久国内精品成人免费 | 久久久久久毛片免费观看 | 在线a亚洲视频播放在线观看 | 日本不卡免费高清一级视频 | 性生活免费视频网站 | 网站在线看 | 国产a一级毛片午夜剧院 | 4tube高清性欧美 | 免费一级网站免费 | 国产一区二区三区在线观看精品 | 老师张开腿让我捅 | 久久精品免费一区二区视 | 中国日本高清免费视频网 | 久草在线最新视频 | 日本特黄a级高清免费酷网 日本特黄特色 | 免费看黄色的网址 | 91精品国产91热久久久久福利 | 国产日本亚洲欧美 | 精品久久看 | 毛片在线播放a | 日本波多野结衣在线 | 久久久久国产视频 | 精品一久久| 一级一片 | 国产国产成人人免费影院 | 成人自拍网 | 成人免费视频在线 |