[ 前端控制请求并发 以及 抽象语法树 | 青训营笔记]

53 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天

什么是前端监控?

AST 是什么

首先:抽象语法树简称为AST,它是一种树状结构来表现语法的结构,树上的每个节点都表示源代码中的一种结构。

AST 有什么用

AST 运用广泛,比如:

  • 编辑器的错误提示、代码格式化、代码高亮、代码自动补全;
  • eslint对代码错误或风格的检查;
  • webpack 通过 babel 转译 javascript 语法;

并且如果你想了解 js 编译执行的原理,那么你就得了解 AST。

例子:

例如:

我们通常会使用webpack打包编译我们的代码将ES6语法降低版本,比如箭头函数变成普通函数。将const、let 声明改成var等等,他都是通过AST来完成的,只不过实现过程比较复杂但大致都是这三部:

  1. js语法解析成AST树
  2. 修改AST
  3. AST转成js语法

控制请求并发 + Blob.slice( ) 文件切片实现 大文件上传

控制每次接口请求的并发数,将30次分解成:并发数为5,分6次请求。这样的话,服务器每次处理5次请求,资源释放出来继续处理下一批请求,从而解决并发拥堵问题~

class TaskQueue {
            constructor(max) {
                this.max = max; // 并发数
                this.min = 0;
                this.taskList = []; // 全部任务
                Promise.resolve().then(() => this.run()) // 等同步代码(addTask)全部执行完成,再执行run
            }

            // 增加任务
            addTask(task) {
                this.taskList.push(task);
            }

            // 执行任务
            async run() {
                if (!this.taskList.length) return;
                const AsyncTasks = [];
                this.min = Math.min(this.max, this.taskList.length) // 当传入的并发数大于任务数,取任务数, 反之取并发数
                // 根据并发数分组
                for (let i = 0; i < this.min; i++) {
                    AsyncTasks.push(this.taskList.shift());
                }
                await this.handleTask(AsyncTasks); // 通过下面递归,这里将会有6个异步任务串联执行

                this.run(); // 递归
            }

            async handleTask(tasks) {
                // 返回promise处理异步任务组
                return new Promise(resolve => {
                    // 遍历任务组,5个异步任务并联执行
                    tasks.forEach(async (task, index) => {
                        await task().then(res => {
                            console.log(res);
                        }).catch((err) => {
                            console.log(err);
                        }).finally(() => {
                            index + 1 === this.min && console.log('===============================');
                            index + 1 === this.min && resolve() // 最后一个任务resolve(),promise完成
                        })
                    })
                })
            }
        }

        function createTask(i) {
            return () => {
                return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        if (i == 4 || i == 15) {  // 测试捕捉错误
                            reject("出错啦~");
                        } else {
                            resolve("成功呀~" + i);
                        }
                    }, 2000);
                });
            };
        }

        const taskQueue = new TaskQueue(5);

        for (let i = 0; i < 30; i++) {
            const task = createTask(i);
            taskQueue.addTask(task);
        }