# 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
为什么会突然想到写这么一个大杂烩的博文呢,必须要从笔者几年前的一次面试说起
当时的我年轻气盛,在简历上放了自己的博客地址,而面试官应该是翻了我的博客,好几道面试题都是围绕着我的博文来提问
其中一个问题,直接使得空气静止了五分钟,然后面试官结束了这次面试,那就是:如何手写一个简易的Promise对象?
在这里,我也先挖个坑,给你们五分钟思考并自己回答一下这个问题~ (答案隐藏在文章中自行查看~)
也是自从那次面试,我告诉自己,工作实战中总结的经验,一定要知其然知其所以然,才可以真正用好这些核心知识点,不积跬步,无以至千里
说了这么多的废话,我们进入今天的博文正题~
目录
- 事件循环(Event Loop)
- 事件循环的执行顺序
- 宏任务(MacroTasks)和微任务(MicroTasks)
- 常见宏任务
- 常见微任务
- 宏任务和微任务的区别
- Promise 对象
- Promise 的基本概念
- 如何创建 Promise 对象
- 如何使用 Promise 对象
- Promise 的优势
- Promise 在工作中的应用场景
- 如何快速入门上手 JavaScript 中的 Promise
- 手写一个简易的 Promise 对象
- 定时器函数
- setTimeout()
- setInterval()
- clearTimeout() 和 clearInterval()
- 定时器函数的使用注意
- 销毁定时器
- 为什么要销毁定时器?
- Vue 中如何销毁定时器?
- React 中如何销毁定时器?
- 补充知识点
- requestAnimationFrame
- setImmediate
- process.nextTick
- Vue中有用到 process.nextTick 吗?
- MutationObserver
- 面试问题合集
什么是事件循环(Event Loop)
事件循环是JavaScript运行时环境的核心机制,用于协调事件、用户交互、脚本、渲染、网络等。
由于JavaScript是单线程的,事件循环使得它能够执行非阻塞操作,即使在处理IO等长时间运行的任务时也能保持响应性。
事件循环的执行顺序
在JavaScript的执行模型中,事件循环按照以下顺序处理任务:
- 执行全局脚本代码,这些同步代码直接运行。
- 当执行栈为空时,事件循环会查看微任务队列。如果队列中有微任务,就一直执行微任务直到队列清空。
- 执行一个宏任务(如由
setTimeout()
或setInterval()
设置的回调)。 - 宏任务执行完毕后,再次执行所有微任务。
- 如果有必要,进行UI渲染。
- 开始下一轮事件循环,处理下一个宏任务。
通过这种机制,JavaScript可以在单线程中有效地处理异步事件,同时保持代码执行的顺序和预期效果。
理解这些概念将帮助你更好地设计和调试JavaScript中的异步代码。
什么是宏任务(MacroTasks)和 微任务(MicroTasks)
宏任务
宏任务是 JavaScript 事件循环中的一个较大的任务单元,每个宏任务在执行时会开启一个新的事件循环
一个宏任务的完成通常会涉及到一个较为完整的工作流程,例如整个脚本的执行、事件(如用户交互事件)、定时器事件(setTimeout、setInterval)以及浏览器的 UI 渲染等
每个宏任务在执行完毕后,会从任务队列中清除
常见宏任务
setTimeout()
:用于设置定时器,在指定的时间间隔后执行任务setInterval()
:用于设置定时器,在指定的时间间隔循环执行任务setImmediate()
:类似setTimeout(fn, 0)
(仅在Node.js中)- IO操作:例如文件读写、网络请求等
- UI渲染:浏览器需要重新渲染页面时触发的任务
requestAnimationFrame
:动画渲染函数
拓展提问:点击和键盘事件是宏任务吗?
在 JavaScript 中,事件(如点击和键盘事件) 通常被处理为任务
但它们不是宏任务(macro-tasks)也不是微任务(micro-tasks),而是作为任务队列中的任务来处理
这些任务在宏任务和微任务之外,有自己的特殊队列,通常称为 任务队列(task queue)
事件(如点击和键盘事件) 通常被放入任务队列,并且它们被视为任务的一种。当
事件循环执行时,它会首先检查宏任务队列,执行完当前宏任务后,再执行所有的微任务。
在微任务执行完毕后,浏览器可能会进行渲染操作(如果需要),然后事件循环会继续到下一个宏任务。
因此,可以说点击和键盘事件是作为任务处理的,而不特定分类为宏任务或微任务。
这种机制确保了 JavaScript 可以在单线程环境中高效地处理异步事件和操作,同时保持代码执行的顺序性和可预测性。
微任务
微任务是在当前宏任务执行完毕后立即执行的任务,事件循环会在每个宏任务之后执行所有队列中的微任务
它们的执行时机是在下一个宏任务开始之前,当前宏任务的后续阶段,微任务的执行时间早于宏任务
微任务通常用于处理异步操作的结果,确保尽可能快地响应
常见微任务
Promise.then/catch/finally
- Promise回调:当Promise状态改变时,会执行相应的回调函数
async
/await
:使用async函数和await关键字进行异步操作时,await后面的代码会作为微任务执行process.nextTick
:在 Node.js 的事件循环的当前阶段完成后、下一个事件循环阶段开始之前,安排一个回调函数尽快执行 (仅在Node.js中)MutaionObserver()
:浏览器中用于观察DOM树的变化,监听DOM变化,当DOM发生变化时触发微任务
宏任务和微任务的区别
任务特征
- 宏任务 有明确的异步任务需要执行和回调;需要其他异步线程支持
- 微任务 没有明确的异步任务需要执行,只有回调,不需要其他异步线程支持
存放位置
- 宏任务 中的事件放在
callback queue
中,由事件触发线程维护 - 微任务 的事件放在微任务队列中,由js引擎线程维护
执行顺序
- 事件循环的过程中,执行栈在同步代码执行完成后,优先检查 微任务 队列是否有任务需要执行,如果没有,再去 宏任务 队列检查是否有任务执行,如此往复
- 微任务 一般在当前循环就会优先执行,而 宏任务 会等到下一次循环
- 因此,微任务 一般比 宏任务 先执行
队列数量
- 微任务 队列只有一个
- 宏任务 队列可能有多个
什么是 Promise
对象
在 JavaScript 中,Promise
对象是异步编程的一种重要机制,它代表了一个尚未完成但预期将来会完成的操作的最终结果。
Promise
提供了一种处理异步操作的方法,使得异步代码易于编写和理解。
Promise
的基本概念
Promise
对象有三种状态:
- Pending(等待中):初始状态,既不是成功,也不是失败。
- Fulfilled(已完成):意味着操作成功完成。
- Rejected(已拒绝):意味着操作失败或出现错误。
如何创建 Promise
对象
Promise
对象是通过 new Promise
构造函数创建的,它接收一个执行器函数作为参数。
这个执行器函数本身接受两个参数:resolve
和 reject
,这两个参数也是函数。
当异步操作成功时,调用 resolve
函数;当操作失败时,调用 reject
函数。
const myPromise = new Promise((resolve, reject) => {// 异步操作const condition = true; // 假设这是某种条件判断if (condition) {resolve('Operation successful');} else {reject('Error occurred');}
});
如何使用 Promise
对象
一旦 Promise
被解析(resolved)或拒绝(rejected),它就不能更改状态。
你可以使用 .then()
方法来处理已完成的 Promise
,并使用 .catch()
方法来处理被拒绝的 Promise
。
还有 .finally()
方法,它在 Promise
完成后被调用,无论其结果如何。
myPromise.then(result => {console.log(result); // 处理结果}).catch(error => {console.error(error); // 处理错误}).finally(() => {console.log('Operation completed'); // 最终都会执行});
Promise
的优势
- 链式调用:
Promise
允许你通过.then()
方法链式调用多个异步操作,每个操作依次执行。 - 错误处理:通过
.catch()
方法,可以集中处理多个异步操作中的错误。 - 并行处理:
Promise.all()
方法允许并行执行多个异步操作,并等待所有操作完成。
Promise
在工作中的应用场景
Promise
在处理如网络请求、文件操作等异步操作时非常有用,它使得代码更加清晰,减少了回调地狱(callback hell)的问题。
通过 Promise
,开发者可以写出更加优雅和可维护的异步代码。
如何快速入门上手JavaScript中的 Promise
?
拓展资料 ———— 快速入门上手JavaScript中的Promise
解答文章开头的问题:如何手写一个简易的 Promise
对象?
function SimplePromise(executor) {let onResolve, onReject;let fulfilled = false;let rejected = false;let called = false; // 防止resolve和reject被多次调用let value;let reason;// resolve函数function resolve(val) {if (!called) {value = val;fulfilled = true;called = true;if (onResolve) {onResolve(val);}}}// reject函数function reject(err) {if (!called) {reason = err;rejected = true;called = true;if (onReject) {onReject(err);}}}// then方法this.then = function(callback) {onResolve = callback;if (fulfilled) {onResolve(value);}return this; // 支持链式调用};// catch方法this.catch = function(callback) {onReject = callback;if (rejected) {onReject(reason);}return this; // 支持链式调用};// 立即执行传入的executor函数try {executor(resolve, reject);} catch (error) {reject(error);}
}// 使用示例
let promise = new SimplePromise((resolve, reject) => {setTimeout(() => {resolve("Success!");// reject("Error!"); // 也可以测试reject情况}, 1000);
});promise.then(result => {console.log(result); // 输出 "Success!"
}).catch(error => {console.log(error);
});
什么是定时器函数
JavaScript 中的定时器函数允许你在一定时间后或者以指定的时间间隔重复执行代码。
这些功能主要通过两个全局函数实现:setTimeout()
和 setInterval()
。
这些函数是异步的,意味着它们不会阻塞代码的执行,而是在指定的延时后将任务加入到 JavaScript 的事件队列中,等待当前执行栈清空后再执行。
setTimeout()
setTimeout()
函数用于在指定的毫秒数后执行一个函数或指定的代码。
它不会阻止后续代码的执行,而是在背后计时,一旦时间到达,就将回调函数加入到事件队列中,等待执行。
语法
let timeoutID = setTimeout(function[, delay, arg1, arg2, ...]);
function
:要执行的函数。delay
:延迟的时间,以毫秒为单位。如果省略,或者为 0,浏览器通常会有最小延迟时间(在HTML5标准中定义为4ms)。arg1, arg2, ...
:传递给函数的额外参数。
使用示例
console.log("Hello");
setTimeout(() => {console.log("World!");
}, 1000);
这个例子会先打印 “Hello”,然后大约1秒后打印 “World!”
setInterval()
setInterval()
函数用于重复调用一个函数或执行代码片段,每隔指定的周期时间(以毫秒为单位)。
它也是非阻塞的,每次间隔时间到达后,就会尝试执行指定的代码。
语法
let intervalID = setInterval(function[, delay, arg1, arg2, ...]);
function
:要定期执行的函数。delay
:执行间隔的时间,以毫秒为单位。arg1, arg2, ...
:传递给函数的额外参数。
使用示例
let counter = 0;
const intervalID = setInterval(() => {console.log("Hello World!");counter++;if (counter === 5) {clearInterval(intervalID);}
}, 1000);
这个例子会每秒打印 “Hello World!”,并在打印5次后停止
clearTimeout() 和 clearInterval()
这两个函数用于取消由 setTimeout()
和 setInterval()
设置的定时器。
语法
clearTimeout(timeoutID)
:取消由setTimeout()
设置的定时器。clearInterval(intervalID)
:取消由setInterval()
设置的定时器。
定时器函数的使用注意
虽然 setTimeout()
和 setInterval()
提供了方便的定时执行功能,但它们并不保证精确的时间控制。
JavaScript 是单线程的,如果事件队列中有其他任务在执行,定时器的回调可能会延迟执行。
此外,浏览器或者环境可能对这些函数的行为有特定的限制,如在后台标签页或未激活的窗口中降低定时器的精度或延迟执行,以优化性能和电池寿命。
拓展提问:为什么要销毁定时器?Vue中如何销毁定时器?React中如何销毁定时器?
在JavaScript中,销毁定时器是一个重要的操作,主要是为了避免不必要的资源占用和潜在的内存泄漏。定时器如果不被适当销毁,可能会导致一些问题,如:
- 继续执行不必要的操作:如果定时器触发的函数不再需要执行,定时器仍然活跃会导致额外的计算,这可能影响程序性能。
- 内存泄漏:在某些情况下,定时器的回调函数可能引用了外部变量或者大型数据结构,如果定时器没有被销毁,这些引用关系可能导致所涉及的内存无法被垃圾回收,从而造成内存泄漏。
Vue中销毁定时器
在Vue中,通常我们会在组件的生命周期钩子中设置和销毁定时器。最常见的做法是在mounted
钩子中创建定时器,并在beforeDestroy
(Vue 2.x)或beforeUnmount
(Vue 3.x)钩子中销毁定时器。例如:
export default {mounted() {this.timer = setInterval(() => {console.log('Interval triggered');}, 1000);},beforeDestroy() { // Vue 2.xclearInterval(this.timer);},beforeUnmount() { // Vue 3.xclearInterval(this.timer);}
}
React中销毁定时器
在React中,定时器通常在组件的生命周期方法或者钩子中设置和清除。使用类组件时,你可以在componentDidMount
中设置定时器,并在componentWillUnmount
中清除。如果使用函数组件和Hooks,可以在useEffect
钩子中处理定时器:
import React, { useEffect } from 'react';function MyComponent() {useEffect(() => {const timer = setInterval(() => {console.log('Interval triggered');}, 1000);// 清理函数return () => clearInterval(timer);}, []); // 空依赖数组表示这个effect只在组件挂载时运行一次return <div>Check the console.</div>;
}
在这个例子中,useEffect
钩子的返回函数负责清除定时器,这个函数会在组件卸载时被调用,从而确保定时器被适当销毁。
通过这些方法,可以确保在组件或应用的生命周期结束时,相关的定时器也被正确清除,避免潜在的问题。
补充知识点:什么是 requestAnimationFrame
?
requestAnimationFrame
是一个由浏览器提供的 API,用于在下一次浏览器重绘之前调用特定的函数,以执行动画或其他视觉更新。
这个函数是专门为动画和连续的视觉更新设计的,它可以帮助你创建平滑的动画效果,因为它能保证在浏览器进行下一次重绘之前更新动画帧。
requestAnimationFrame
的特点
- 高效性能:
requestAnimationFrame
会将动画函数的执行时机安排在浏览器的下一次重绘之前,这样可以保证动画的更新和浏览器的绘制操作同步进行,从而减少画面撕裂和不必要的计算和渲染,提高性能。 - 节能:相比于
setTimeout
或setInterval
,requestAnimationFrame
是更智能的,因为它会在浏览器标签页不可见时自动暂停,从而减少CPU、GPU和电力的消耗。 - 简单的使用方式:
requestAnimationFrame
只需要一个回调函数作为参数,浏览器会自动计算出最适合的调用时间。
requestAnimationFrame
的使用示例
假设你想要创建一个简单的动画,使一个元素在水平方向上移动:
let xPos = 0;function animate() {xPos += 5; // 每帧向右移动5像素element.style.transform = `translateX(${xPos}px)`; // 更新元素位置if (xPos < 500) { // 如果元素还没移动到500像素的位置,继续动画requestAnimationFrame(animate);}
}requestAnimationFrame(animate); // 开始动画
在这个示例中,animate
函数会被连续调用,每次调用都会将元素向右移动5像素,直到它达到500像素的位置。
requestAnimationFrame
在工作中应用的注意事项
requestAnimationFrame
需要在每一帧都重新调用来继续动画。- 如果动画或者视觉更新不再需要,应当使用
cancelAnimationFrame
来取消回调函数的执行,避免不必要的性能消耗。 - 由于
requestAnimationFrame
的调用时间是由浏览器决定的,通常它的频率会与浏览器的刷新率相匹配,例如大多数设备上是每秒60次(即60Hz),但这可能会因设备而异。
补充知识点:什么是 setImmediate
?
setImmediate
是一个在 Node.js 环境中使用的函数,用于安排一个回调函数在当前事件循环结束后、下一次事件循环开始前被立即执行。
这个函数是特定于 Node.js 的,不是 Web 标准的一部分,因此在浏览器环境中不可用。
setImmediate
的功能和用途
setImmediate
的主要用途是将一些需要尽快执行但不必阻塞当前正在执行的操作的代码延迟执行。它与 setTimeout
和 process.nextTick
类似,但行为略有不同:
setImmediate
安排的任务会在当前事件循环的“check”阶段执行。setTimeout(fn, 0)
会在定时器阶段执行,通常会有一小段延迟(最小延迟时间,通常是1毫秒,取决于环境)。process.nextTick
会在当前事件循环的任何阶段结束后立即执行,甚至在进入下一个事件循环阶段之前。
setImmediate
的使用示例
下面是一个简单的 Node.js 示例,演示了 setImmediate
的用法:
console.log('开始执行');
setImmediate(() => {console.log('执行 setImmediate 回调');
});
console.log('结束执行');
在这个例子中,输出将会是:
开始执行
结束执行
执行 setImmediate 回调
这表明 setImmediate
安排的回调确实是在当前事件循环的末尾执行的。
setImmediate
在工作中应用的注意事项
- 非标准 API:
setImmediate
是一个非标准的 API,只在 Node.js 环境中可用。在浏览器中,你可能需要使用setTimeout(fn, 0)
来达到类似的效果,虽然这两者在行为上有细微的差别。 - 使用场景:通常用于处理长时间运行的操作后需要快速响应的场景,或者在处理完一些同步任务后需要尽快执行的异步代码。
补充知识点:什么是 process.nextTick
?
process.nextTick
是 Node.js 环境中的一个函数,它用于在 Node.js 的事件循环的当前阶段完成后、下一个事件循环阶段开始之前,安排一个回调函数尽快执行。
这意味着无论在事件循环的哪个阶段调用 process.nextTick
,提供的回调函数都会在当前操作完成后立即执行,但在任何I/O事件(包括定时器)或者执行其他计划任务之前执行。
process.nextTick
的功能和用途
process.nextTick
主要用于确保在当前执行栈运行完毕后、在进行任何异步操作之前立即处理给定的回调。
这对于处理错误、清理资源或者在继续其他事件之前进行其他紧急计算是非常有用的。
与 setImmediate
的区别
尽管 process.nextTick
和 setImmediate
都用于安排异步操作,但它们的执行时间点不同:
process.nextTick
回调在同一事件循环阶段尽可能早地执行,即在任何I/O事件和定时器之前。setImmediate
设计为在当前事件循环的所有I/O事件处理完毕后执行,即在下一个事件循环迭代的开始。
process.nextTick
的使用示例
下面是一个 Node.js 示例,展示了 process.nextTick
的使用:
console.log('开始执行');
process.nextTick(() => {console.log('执行 process.nextTick 回调');
});
console.log('结束执行');
在这个例子中,输出将会是:
开始执行
结束执行
执行 process.nextTick 回调
这表明 process.nextTick
安排的回调确实是在当前事件循环的末尾、在其他异步事件之前执行的。
process.nextTick
在工作中应用的注意事项
- 递归调用:如果
process.nextTick
被递归调用,或在一个循环中大量调用,它可以导致I/O饿死,因为它会在处理任何I/O事件之前不断地将新的回调加入到队列中。 - 用途选择:
process.nextTick
非常适合在当前操作完成后立即需要运行的情况,例如在事件或低级逻辑之后立即处理错误或进行清理。
框架拓展:Vue 中有用到 process.nextTick
吗?
Vue.js 中也使用了 process.nextTick
,或者更具体地说,它使用了与之类似的异步延迟功能。
process.nextTick
是 Node.js 的一个特性,但在浏览器环境中,Vue 使用的是 nextTick
方法。
这是 Vue 的全局 API,用于在下一个 DOM 更新循环结束后执行延迟回调。
在内部,Vue 会尝试使用原生的 Promise.then
、MutationObserver
,或者 setImmediate
,最后退回到 setTimeout(fn, 0)
。
Vue中 nextTick
的应用
- 确保 DOM 更新完成:Vue 的数据绑定和 DOM 更新是异步的。当你更改数据后,DOM 不会立刻更新。
nextTick
允许你在 DOM 更新完成后立即运行回调函数,这对于 DOM 依赖的操作非常有用。 - 解决状态更新问题:有时候,你可能在同一方法中多次更改数据,使用
nextTick
可以确保所有的 DOM 更新都完成后再执行某些操作。
Vue中 nextTick
的使用示例
new Vue({el: '#app',data: {message: 'Hello'},methods: {updateMessage() {this.message = 'Updated message';this.$nextTick(() => {// 这个回调将在 DOM 更新后执行// `$nextTick()` 用来确保 `console.log('DOM updated')` 的执行发生在 DOM 真正更新之后console.log('DOM updated');});}}
});
补充知识点:什么是 MutationObserver
?
MutationObserver
是一个强大的 Web API,用于监视 DOM(文档对象模型)的变化。
当 DOM 元素被添加、删除或修改时,MutationObserver
可以被用来异步地通知这些变化,使开发者能够响应这些变化并执行相应的操作。
MutationObserver
的功能
MutationObserver
主要用于监视以下类型的 DOM 变化:
- 子节点的添加或删除。
- 属性的添加、删除或修改。
- 文本内容的变更。
- 更多其他类型的 DOM 变化。
MutationObserver
的用途
这使得 MutationObserver
在开发复杂的 Web 应用时非常有用,特别是在需要响应 DOM 变化来执行某些操作的情况下,如动态内容的加载、用户界面的自动更新等。
如何使用 MutationObserver
要使用 MutationObserver
,你需要创建一个观察者实例,定义一个回调函数来处理变化,然后指定要监视的 DOM 节点和具体的观察选项。
MutationObserver
的简易示例
// 监视目标节点
const targetNode = document.getElementById('some-id');
// 配置观察选项:
const config = { attributes: true, childList: true, subtree: true };
// 当观察到变动时执行的回调函数
const callback = function(mutationsList, observer) {for(let mutation of mutationsList) {if (mutation.type === 'childList') {console.log('A child node has been added or removed.');} else if (mutation.type === 'attributes') {console.log(`The ${mutation.attributeName} attribute was modified.`);}}
};
// 创建一个观察者对象并传入回调函数
const observer = new MutationObserver(callback);
// 开始观察已配置的变动
observer.observe(targetNode, config);
// 之后,你可以停止观察
// observer.disconnect();
MutationObserver
在工作中应用的注意事项
- 性能考虑:虽然
MutationObserver
是异步的,但过度使用或监视大量的 DOM 变化仍可能影响性能。合理配置观察选项,只监视必要的变化,可以帮助避免性能问题。 - 内存管理:使用
MutationObserver
时应确保在不需要时断开观察(使用disconnect
方法),以避免内存泄漏。
面试问题合集
恭喜你耐心看完本文了,对照下方的问题列表,自我提问一下吧~
什么是 事件循环?
事件循环 的执行顺序是什么?
什么是 宏任务和微任务?
宏任务和微任务 有什么区别?
点击和键盘事件 是宏任务吗?
什么是Promise
对象?
如何手写一个简易的Promise
对象?
为什么Promise
比setTimeout
快?
Promise.all
和Promise.race
有什么区别?
什么是requestAnimationFrame
?
什么是setImmediate
?
什么是process.nextTick
?
Vue 中有用到process.nextTick
吗?
什么是MutationObserver
?
Vue中如何销毁定时器?React中如何销毁定时器?为什么要销毁定时器?
我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~ 😃
转发请注明参考文章地址,非常感谢!!!
相关文章:

# 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
为什么会突然想到写这么一个大杂烩的博文呢,必须要从笔者几年前的一次面试说起 当时的我年轻气盛,在简历上放了自己的博客地址,而面试官应该是翻了我的博客,好几道面试题都是围绕着我的博文来提问 其中一个问题,直接…...

神经网络与深度学习——第14章 深度强化学习
本文讨论的内容参考自《神经网络与深度学习》https://nndl.github.io/ 第14章 深度强化学习 深度强化学习 强化学习(Reinforcement Learning,RL),也叫增强学习,是指一类从与环境交互中不断学习的问题以及解决这类问题…...

centOS 编译C/C++
安装C和C编译器 yum -y install gcc*查看CenterOS系统信息 cat /etc/system-releaseCentOS Linux release 8.2.2004 (Core)查看gcc版本 gcc --versiongcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-4) Copyright (C) 2018 Free Software Foundation, Inc. This is free software…...

java——网络原理初识
T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 小比特 大梦想 目录 1.网络通信概念初识1.1 IP地址1.2端口号1.3协议1.3.1协议分层协议分层带来的好处主要有两个方面 1.3.2 TCP/IP五层 (或四层模型)1.3.3 协议的层和层之间是怎么配合工作的 1.网络通信概念初识…...

js怎么判断是否为手机号?js格式校验方法
数据格式正确与否是表单填写不可避免的一个流程,现整理一些较为常用的信息格式校验方法。 判断是否为手机号码 // 判断是否为手机号码 function isPhoneNumber(phone) {return /^[1]\d{10}$/.test(phone) }判断是否为移动手机号 function isChinaMobilePhone(phon…...

深入理解Java中的方法重载:让代码更灵活的秘籍
关注微信公众号 “程序员小胖” 每日技术干货,第一时间送达! 引言 在Java编程的世界里,重载(Overloading)是一项基础而强大的特性,它让我们的代码更加灵活、可读性强。对于追求高效、优雅编码的开发者而言,掌握方法重…...

鸿蒙ArkTS声明式开发:跨平台支持列表【显隐控制】 通用属性
显隐控制 控制组件是否可见。 说明: 开发前请熟悉鸿蒙开发指导文档: gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本…...

每日一题——Java编程练习题
题目: 键盘录入两个数字number1和number2表示一个范围,求这个范围之内的数字和。 我写的代码: public class Test {public static void main(String[] args) {Scanner sc new Scanner(System.in);System.out.print("输入第一个数:&q…...

java编辑器中如何调试程序?
目录 如何调试java程序? 待续、更新中 如何调试java程序? 1 看错误信息 2 相应位置输入输出信息: System.out.println("测试信息1 "); 以此查看哪条语句未进行输入 待续、更新中 1 顿号、: 先使用ctrl. ,再使用一遍切回 2 下标: 21 2~1~ 3 上标: 2…...

第四范式Q1业务进展:驰而不息 用科技锻造不朽价值
5月28日,第四范式发布今年前三个月的核心业务进展,公司坚持科技创新,业务稳步拓展,用人工智能为千行万业贡献价值。 今年前三个月,公司总收入人民币8.3亿元,同比增长28.5%,毛利润人民币3.4亿元&…...

SpringBoot整合Kafka的快速使用教程
目录 一、引入Kafka的依赖 二、配置Kafka 三、创建主题 1、自动创建(不推荐) 2、手动动创建 四、生产者代码 五、消费者代码 六、常用的KafKa的命令 Kafka是一个高性能、分布式的消息发布-订阅系统,被广泛应用于大数据处理、实时日志分析等场景。Spring B…...

低边驱动与高边驱动
一.高边驱动和低边驱动 低边驱动(LSD): 在电路的接地端加了一个可控开关,低边驱动就是通过闭合地线来控制这个开关的开关。容易实现(电路也比较简单,一般由MOS管加几个电阻、电容)、适用电路简化和成本控制的情况。 高边驱动&am…...

【C++】入门(二):引用、内联、auto
书接上回:【C】入门(一):命名空间、缺省参数、函数重载 文章目录 六、引用引用的概念引用的使用场景1. 引用做参数作用1:输出型参数作用2:对象比较大,减少拷贝,提高效率 2. 引用作为…...

编程学习 (C规划) 6 {24_4_18} 七 ( 简单扫雷游戏)
首先我们要清楚扫雷大概是如何实现的: 1.布置雷 2.扫雷(排查雷) (1)如果这个位置是雷就炸了,游戏结束 (2)如果不是雷,就告诉周围有几个雷 3.把所有不是雷的位置都找…...

【AI】llama-fs的 安装与运行
pip install -r .\requirements.txt Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved.Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows(venv) PS D:\XTRANS\pythonProject>...

Android NDK系列(五)内存监控
在日常的开发中,内存泄漏是一种比较比较棘手的问题,这是由于其具有隐蔽性,即使发生了泄漏,很难检测到并且不好定位到哪里导致的泄漏。如果程序在运行的过程中不断出现内存泄漏,那么越来越多的内存得不到释放࿰…...

软件设计师,下午题 ——试题六
模型图 简单工厂模式 工厂方法模式抽象工厂模式生成器模式原型模式适配器模式桥接模式组合模式装饰(器)模式亨元模式命令模式观察者模式状态模式策略模式访问者模式中介者模式 简单工厂模式 工厂方法模式 抽象工厂模式 生成器模式 原型模式 适配器模式 桥…...

《Kubernetes部署篇:基于麒麟V10+ARM64架构部署harbor v2.4.0镜像仓库》
总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:企业级K8s集群运维实战 一、环境信息 K8S版本 操作系统 CPU架构 服务版本 1.26.15 Kylin Linux Advanced Server V10 ARM64 harbor v2.4.0 二、部…...

远程工作/线上兼职网站整理(数字游民友好)
文章目录 国外线上兼职网站fiverrupwork 国内线上兼职网站甜薪工场猪八戒网云队友 国外线上兼职网站 fiverr https://www.fiverr.com/start_selling?sourcetop_nav upwork https://www.upwork.com/ 国内线上兼职网站 甜薪工场 https://www.txgc.com/ 猪八戒网 云队友 …...

elasticsearch7.15实现用户输入自动补全
Elasticsearch Completion Suggester(补全建议) Elasticsearch7.15安装 官方文档 补全建议器提供了根据输入自动补全/搜索的功能。这是一个导航功能,引导用户在输入时找到相关结果,提高搜索精度。 理想情况下,自动补…...

掌握正则表达式的力量:全方位解析PCRE的基础与进阶技能
Perl 兼容正则表达式(PCRE)是 Perl scripting language 中所使用的正则表达式语法标准。这些正则表达式在 Linux 命令行工具(如 grep -P)及其他编程语言和工具中也有广泛应用。以下是一些基础和进阶特性,帮你掌握和使用…...

FastFM库,一款强大神奇的Python系统分析预测的工具
FastFM库概述 在机器学习领域,Factorization Machines(FM)是处理稀疏数据集中特征间交互的重要工具.Python的fastFM库提供了高效的实现,特别适合用于推荐系统、评分预测等任务.本文将全面介绍fastFM的安装、特性、基本和高级功能,并结合实际应用场景展示…...

R语言绘图 --- 饼状图(Biorplot 开发日志 --- 2)
「写在前面」 在科研数据分析中我们会重复地绘制一些图形,如果代码管理不当经常就会忘记之前绘图的代码。于是我计划开发一个 R 包(Biorplot),用来管理自己 R 语言绘图的代码。本系列文章用于记录 Biorplot 包开发日志。 相关链接…...

用于日常任务的实用 Python 脚本
Python 是一种多功能编程语言,以其简单易读而闻名。它广泛应用于从 Web 开发到数据分析等各个领域。Python 脚本,它们可以通过自动执行常见任务来使您的生活更轻松。 用于日常任务的实用 Python 脚本 1. 使用 Pandas 进行数据分析2. 使用 BeautifulSoup …...

7-Zip是什么呢
1. 简介 7-Zip 是一个功能强大、免费开源的文件压缩和解压缩工具,适用于个人用户和企业用户,可以在多种操作系统上进行使用,并且支持广泛的压缩格式和高级功能。 2. 特点与优势 开源免费:7-Zip 是免费的开源软件,可…...

Satellite Stereo Pipeline学习
1.在Anaconda某个环境中安装s2p pip install s2p 2.在Ubuntu系统中安装s2p源代码 git clone https://github.com/centreborelli/s2p.git --recursive cd s2p pip install -e ".[test]" 3.在s2p中进行make all处理 中间会有很多情况,基本上哪个包出问题…...

linux-gpio
在Linux shell中测试GPIO通信,通常需要使用GPIO的设备文件,这些文件通常位于/sys/class/gpio目录下。要使用特定的GPIO引脚,比如GPIO92,你需要执行以下步骤: 导出GPIO引脚:首先,需要确保GPIO92已…...

C# 代码配置的艺术
文章目录 1、代码配置的定义及其在软件工程中的作用2、C# 代码配置的基本概念和工具3、代码配置的实践步骤4、实现代码配置使用属性(Properties)使用配置文件(Config Files)使用依赖注入(Dependency Injection…...

268 基于matlab的模拟双滑块连杆机构运动
基于matlab的模拟双滑块连杆机构运动,并绘制运动动画,连杆轨迹可视化输出,并输出杆件质心轨迹、角速度、速度变化曲线。可定义杆长、滑块速度,滑块初始位置等参数。程序已调通,可直接运行。 268 双滑块连杆机构运动 连…...

进口铝合金电动隔膜泵
进口铝合金电动隔膜泵是一种高效、可靠的工业泵,其特点、性能与应用广泛,以下是对其的详细分析: 特点 材质与结构: 采用铝合金材料制造,具有良好的耐腐蚀性和轻量化特点。铝合金材质使得泵体结构紧凑、轻便ÿ…...