并发控制

并发控制 function timeout(timer) { return new Promise((res) => setTimeout(res, timer)); } class SuperTask { constructor(parallelCount = 2) { this.parallelCount = parallelCount; //并发数 this.tasks = []; //还在排队的任务 this.runningCount = 0; //正在执行的任务数 } add(task) { return new Promise((resolve, reject) => { this.tasks.push({ task, resolve, reject, }); this._run(); }); } _run() { while (this.runningCount < this.parallelCount && this.tasks.length) { const { task, resolve, reject } = this.tasks.shift(); //取出第一个任务 task() .then(resolve, reject) .finally(() => { //不管成功失败都会去再次尝试执行任务 this.runningCount--; this._run(); }); this.runningCount++; } } } const superTask = new SuperTask(); function addTask(time, name) { superTask .add(() => timeout(time)) .then(() => { console.log(`任务${name}完成`); }); } addTask(10000, 1); //10000ms后输出 任务1完成 addTask(5000, 2); // 5000ms后输出 任务2完成 addTask(3000, 3); // 8000ms后输出 任务3完成 addTask(4000, 4); // 12000ms后输出 任务4完成 addTask(5000, 5); // 15000ms后输出 任务5完成

April 28, 2025 · 1 min · 122 words · chrisworkalx

高度过渡问题

前言 在 CSS 中,我们经常需要处理元素的高度过渡问题。例如,当元素的内容发生变化时,我们需要动态地调整元素的高度,以适应新的内容。但是,如果直接设置元素的高度,可能会导致元素的高度过渡不自然,甚至出现闪烁的现象。因此,我们需要使用一些技巧来处理高度过渡问题。 使用 transition 属性 在 CSS 中,我们可以使用 transition 属性来处理元素的高度过渡问题。transition 属性可以指定元素在一段时间内平滑地过渡到新的状态。例如: .element { transition: height 0.5s ease; } 在这个例子中,我们指定了元素的高度在 0.5 秒内平滑地过渡到新的状态。ease 是一个缓动函数,它可以使过渡更加自然。 使用 max-height 属性 项目地址 1 在 CSS 中,我们可以使用 max-height 属性来限制元素的最大高度。例如: .element { max-height: 0; overflow: hidden; transition: max-height 0.5s ease; } 在这个例子中,我们指定了元素的最大高度为 0,并且隐藏了元素的内容。当元素的内容发生变化时,我们可以通过 JavaScript 来动态地调整元素的最大高度,以适应新的内容。例如: function toggleElement() { var element = document.getElementById("element"); if (element.style.maxHeight === "0px") { element.style.maxHeight = element.scrollHeight + "px"; } else { element.style.maxHeight = "0px"; } } 使用 height:auto 属性 项目地址 2 在 CSS 中,我们可以使用 height:auto 属性来让元素的高度自动适应内容。例如: .element { height: auto; transition: height 0.5s ease; } const btn = document.querySelector(".btn"); const content = document.querySelector(".content"); btn.onmouseenter = () => { content.style.height = "auto"; const h = content.offsetHeight; content.style.height = "0px"; //让浏览器强制渲染 //读取任何几何位置信息,都可触发 浏览器强制渲染一次 content.offsetHeight; content.style.transition = "0.5s"; content.style.height = h + "px"; }; btn.onmouseleave = () => { content.style.transition = "0.5s"; content.style.height = "0px"; }; 新的特性 实验方案 项目 3 ...

April 24, 2025 · 2 min · 219 words · chrisworkalx

消除异步函数的传染性

前言 最近在阅读 React 源码,发现了一个很有意思的现象,就是 React.Suspense 的原理,它使得异步函数不再具有传染性,即异步函数不再需要层层传递,而是直接在顶层进行控制。 异步函数的传染性 在 JavaScript 中,异步函数通常是通过回调函数来实现的,例如: function fetchData(callback) { setTimeout(() => { callback("data"); }, 1000); } fetchData((data) => { console.log(data); }); 在上面的例子中,fetchData 函数是一个异步函数,它接受一个回调函数作为参数,当数据获取完成后,调用回调函数将数据传递出去。 但是,如果需要在一个异步函数中调用另一个异步函数,那么就需要将回调函数传递下去,例如: function fetchData(callback) { setTimeout(() => { callback("data"); }, 1000); } function fetchData2(callback) { fetchData((data) => { callback(data + "2"); }); } fetchData2((data) => { console.log(data); }); 在上面的例子中,fetchData2 函数是一个异步函数,它调用了 fetchData 函数,并将回调函数传递给了 fetchData 函数。这样,当 fetchData 函数获取到数据后,就会调用回调函数将数据传递给 fetchData2 函数,然后 fetchData2 函数再调用回调函数将数据传递给顶层函数。 但是,如果需要在一个异步函数中调用多个异步函数,那么就需要将回调函数层层传递下去,例如: function fetchData(callback) { setTimeout(() => { callback("data"); }, 1000); } function fetchData2(callback) { fetchData((data) => { callback(data + "2"); }); } function fetchData3(callback) { fetchData2((data) => { callback(data + "3"); }); } fetchData3((data) => { console.log(data); }); 在上面的例子中,fetchData3 函数是一个异步函数,它调用了 fetchData2 函数,并将回调函数传递给了 fetchData2 函数。然后 fetchData2 函数再调用了 fetchData 函数,并将回调函数传递给了 fetchData 函数。这样,当 fetchData 函数获取到数据后,就会调用回调函数将数据传递给 fetchData2 函数,然后 fetchData2 函数再调用回调函数将数据传递给 fetchData3 函数,最后 fetchData3 函数再调用回调函数将数据传递给顶层函数。 ...

April 23, 2025 · 3 min · 479 words · chrisworkalx