返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解JavaScript进度管理
  • 468
分享到

详解JavaScript进度管理

2024-04-02 19:04:59 468人浏览 薄情痞子
摘要

目录前言问题原理测试前言 我们写程序的时候会经常遇到显示进度的需求,如加载进度、上传进度等。 最常见的实现方式是通过记录已完成数量(loadedCount)和总数量(totalCou

前言

我们写程序的时候会经常遇到显示进度的需求,如加载进度、上传进度等。
最常见的实现方式是通过记录已完成数量(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'));

这种方式的优点是能避开全局管理loadedCount和totalCount,把这部分工作交回资源内部管理,它要做的只是对大任务进行归并计算。

缺点也很明显,需要对onProgress接口进行一次统一。在已有项目中推进难度很大,所以比较适合新项目或者小项目去实践。

以上就是JavaScript进度管理的详细内容,更多关于JavaScript进度管理的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解JavaScript进度管理

本文链接: https://lsjlt.com/news/125011.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详解JavaScript进度管理
    目录前言问题原理测试前言 我们写程序的时候会经常遇到显示进度的需求,如加载进度、上传进度等。 最常见的实现方式是通过记录已完成数量(loadedCount)和总数量(totalCou...
    99+
    2024-04-02
  • 详解JavaScript+Canvas绘制环形进度条
    目录效果图思考实现思路具体代码实现效果图 思考 移动端的场景里经常会出现环形进度条的功能,在实现这个功能前,我预想的解决方案大致有: echarts、antv、canvas、svg...
    99+
    2024-04-02
  • javascript Redux的状态管理详解
    所谓的状态管理,就是对应用程序中的数据进行管理。 理念:凡是数据流管理混乱的项目,几乎都上不了线。好的项目,必须有非常良好的数据流管理。 如何使用Redux?记住“3个3...
    99+
    2024-04-02
  • Node.js进程管理之子进程详解
    一、理论 之前看多进程这一章节时发现这块东西挺多,写Process模块的时候也有提到,今天下午午休醒来静下心来好好的看了一遍,发现也不是太难理解。 Node.js是单线程的,对于现在...
    99+
    2024-04-02
  • 钉钉项目进度管理
    1. 什么是钉钉项目进度管理? 钉钉项目进度管理是一种利用钉钉平台进行项目进度跟踪和管理的方法。钉钉是一款集即时通讯、日程安排、文件共享等功能于一体的企业级办公软件,通过钉钉平台可以方便地进行项目管理和团队协作。 2. 钉钉项目进度管理的...
    99+
    2023-10-28
    进度 项目
  • 钉钉工程进度管理
    首先,钉钉的工程进度管理非常重要。工程进度管理可以帮助团队成员了解项目的整个进度,以及每个任务的预计完成时间。通过实时跟踪任务的进度,可以及时发现问题并采取措施来解决它们,确保项目按时完成。同时,可以为每个任务分配负责人,以便更好地管理任务...
    99+
    2023-10-28
    工程进度
  • Node.js进程管理之进程集群详解
    一、cluster模块 Node.js是单线程处理,对于高并发的请求怎么样能增加吞吐量呢?为了提高服务器的利用率,能不能多核的来处理呢?于是就有了cluster模块。 cluster...
    99+
    2024-04-02
  • 详解使用PM2管理nodejs进程
    pm2 是一个带有负载均衡功能的Node应用的进程管理器. 当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的。 它非常适合IaaS结构,但不要把它用于P...
    99+
    2022-06-04
    详解 进程 nodejs
  • Nodejs进程管理模块forever详解
    接下来,就让我们看看forever能不能实现目标。一、forever介绍 forever是一个简单的命令式nodejs的守护进程,能够启动,停止,重启App应用。forever完全基于命令行操作,在fore...
    99+
    2022-06-04
    详解 进程 管理模块
  • linux系统之进程管理详解
    目录1、进程与线程的概念2、什么是进程管理3、进程管理的作用4、linux进程的几种状态5、进程与线程的关系(1)线程与进程的关系(2)总结1、进程与线程的概念 来源百度百科: 进程(Process) 是计算机中的程序关...
    99+
    2022-06-04
    Linux进程管理及作用 Linux进程管理总结
  • Python进程管理神器Supervisor详解
    目录一、简介二、安装三、创建配置文件四、初试五、Web 界面附录:supervisorctl 常用命令一、简介 Supervisor 是一款 Python 开发的进程管理系统,允许用...
    99+
    2024-04-02
  • Nginx进程管理和重载原理详解
    进程结构图 Nginx是多进程结构,多进程结构设计是为了保证Nginx的高可用高可靠,包含: master进程:父进程,负责worker进程的管理 worker进程...
    99+
    2024-04-02
  • Node.js进程管理之Process模块详解
    在前面Node.js事件运行机制也有提到,Node.js应用在单个线程运行,但是现在大部分服务器都是多处理器,为了方便使用多个进程,Node.js提供了3个模块。Process模块提...
    99+
    2024-04-02
  • 钉钉生产进度管理系统
    首先,钉钉生产进度管理系统可以实时追踪产品的生产进度,让生产管理者能够及时发现生产中存在的问题,采取相应的措施,确保生产进度的按时完成。同时,系统还可以通过智能排程,自动调度生产资源,实现高效的生产计划。 其次,钉钉生产进度管理系统可以实...
    99+
    2023-10-28
    管理系统 进度
  • JavaScript内存管理与闭包实例详解
    目录1. 内存管理的理解1.1 认识内存管理1.2 JavaScript的内存管理2. 垃圾回收(GC)2.1 认识垃圾回收2.2 GC算法 – 引用计数2.3 GC算法...
    99+
    2024-04-02
  • 详解node nvm进行node多版本管理
    写在前面 nvm(nodejs version manager)是nodejs的管理工具,如果你需要快速更新node版本,并且不覆盖之前的版本;或者想要在不同的node版本之间进行切换; 使用nvm来安装我...
    99+
    2022-06-04
    详解 版本 node
  • node进程管理工具PM2用法详解
    PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。 安装 npm install -g pm2 常用命...
    99+
    2024-04-02
  • C语言进度条的实现原理详解
    目录\r和\n行缓冲区进度条\r和\n 在程序里面,\r和\n分别代表什么意思? \r:表示“回车”,即回到当前行的起始位置 \n:表示换行,即列不变,另其一...
    99+
    2024-04-02
  • 钉钉项目进度管理甘特图
    作为一款在线协作工具,钉钉在项目进度管理方面做得非常出色。通过甘特图,我们可以清晰地看到项目当前的进展情况,以及下一步的计划。下面,就让我们一起来看看钉钉项目进度管理甘特图是如何运作的。 一、任务分类 钉钉项目进度管理甘特图中,任务分类可...
    99+
    2023-10-28
    进度 项目 甘特图
  • MySQL8.0UndoTablespace管理详解
    目录1. UNDO 基础概念2. UNDO 相关参数2.1 参数含义3. UNDO 表空间运维3.1 查看UNDO的基本信息3.2 添加/active/inactive/删除UNDO...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作