当前位置: 首页 > news >正文

《异步江湖:XHR、Promise 与 Event Loop 的恩怨情仇》

XMLHttpRequest 

XMLHttpRequest(简称 XHR)是浏览器提供的一个 JavaScript 对象,用于在客户端和服务器之间发送 HTTP 请求。它是实现 AJAX(Asynchronous JavaScript and XML) 技术的核心工具,允许网页在不重新加载的情况下与服务器交换数据并更新部分页面内容。。


1. 基本用法

创建 XHR 对象

const xhr = new XMLHttpRequest();

配置请求

使用 open() 方法初始化请求:

xhr.open(method, url, async);
  • method:HTTP 方法(如 GETPOST)。

  • url:请求的目标 URL。

  • async:是否异步(默认为 true)。

示例
xhr.open('GET', 'https://api.example.com/data', true);

发送请求

使用 send() 方法发送请求:

xhr.send();
  • 对于 POST 请求,可以在 send() 中传递请求体数据:

    xhr.send(JSON.stringify({ key: 'value' }));

处理响应

通过 onreadystatechange 事件监听请求状态变化:

xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log('响应数据:', xhr.responseText);}
};
 

2. XHR 对象的属性和方法

属性

属性说明
readyState请求状态:
- 0:未初始化
- 1:已打开
- 2:已发送
- 3:接收中
- 4:完成
statusHTTP 状态码(如 200、404、500)。
statusTextHTTP 状态文本(如 OKNot Found)。
responseText服务器返回的文本数据(字符串形式)。
responseXML服务器返回的 XML 数据(如果响应内容是 text/xml)。
responseType设置响应类型(如 jsontextblob)。
response根据 responseType 返回的响应数据。

方法

方法说明
open(method, url)初始化请求。
send(body)发送请求,body 是可选的请求体数据。
setRequestHeader(header, value)设置请求头(如 Content-Type)。
abort()取消请求。

3. 完整示例

GET 请求

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log('响应数据:', xhr.responseText);}
};
xhr.send();

POST 请求

const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.example.com/submit', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log('响应数据:', xhr.responseText);}
};
xhr.send(JSON.stringify({ username: 'john', password: '123456' }));

4. 事件监听

除了 onreadystatechange,XHR 还支持以下事件:

事件说明
onload请求成功完成时触发。
onerror请求失败时触发。
onprogress请求正在处理中时触发(用于监控上传/下载进度)。
示例

xhr.onload = function() {if (xhr.status === 200) {console.log('响应数据:', xhr.responseText);}
};
xhr.onerror = function() {console.error('请求失败');
};
xhr.onprogress = function(event) {if (event.lengthComputable) {console.log(`已接收 ${event.loaded} / ${event.total} 字节`);}
};

5. 跨域请求

XHR 默认受 同源策略 限制,无法直接访问不同源的资源。可以通过以下方式解决跨域问题:

  1. CORS(跨域资源共享)
    服务器设置 Access-Control-Allow-Origin 响应头。

  2. JSONP
    通过 <script> 标签加载跨域数据(仅支持 GET 请求)。

  3. 代理服务器
    通过同源服务器转发请求。


6. 与 Fetch API 的对比

特性XMLHttpRequestFetch API
语法基于回调,代码冗长基于 Promise,语法简洁
流式数据处理不支持支持
请求取消支持(abort()支持(AbortController
兼容性支持所有浏览器(包括 IE)不支持 IE
错误处理需手动检查状态码自动处理网络错误

7.查询参数

  1. 什么是查询参数:携带额外信息给服务器,返回匹配想要的数据

  2. 查询参数原理要携带的位置和语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2

  3. 所以,原生 XHR 需要自己在 url 后面携带查询参数字符串,没有 axios 帮助我们把 params 参数拼接到 url 字符串后面了

特性XMLHttpRequestAxios
语法需要手动拼接 URL 或使用 URLSearchParams提供 params 配置项,自动处理查询参数
代码复杂度代码冗长,需手动处理细节代码简洁,封装了底层细节
错误处理需手动检查状态码和错误基于 Promise,支持 catch 捕获错误
兼容性支持所有浏览器(包括 IE)不支持 IE
功能扩展功能有限,需自行封装提供拦截器、请求取消等高级功能

Promise

1. 什么是 Promise?

Promise 是 JavaScript 提供的一种用于 处理异步操作 的对象。它用于解决 回调地狱 问题,使异步代码更易读、可维护。

Promise 对象表示一个 尚未完成但预计会在未来完成的操作,它可以是:

  • 进行中(pending):初始状态,既没有成功也没有失败。
  • 已完成(fulfilled):操作成功,返回一个值(由 resolve() 处理)。
  • 已拒绝(rejected):操作失败,返回一个错误(由 reject() 处理)。
2. Promise 语法
const myPromise = new Promise((resolve, reject) => {setTimeout(() => {let success = true; // 模拟成功或失败if (success) {resolve("操作成功!");} else {reject("操作失败!");}}, 1000);
});// 处理 Promise 结果
myPromise.then((result) => console.log(result)) // 操作成功!.catch((error) => console.error(error)) // 操作失败!.finally(() => console.log("操作完成")); // 无论成功或失败都会执行
3. Promise 链式调用

支持多个 .then() 串联执行,避免回调地狱

new Promise((resolve) => resolve(1)).then((num) => num * 2).then((num) => num * 3).then(console.log); // 6
4. 常用 Promise 方法
方法作用
Promise.all()同时执行多个 Promise,全部成功返回数组,否则返回第一个失败的
Promise.race()返回第一个完成的 Promise(无论成功或失败)
Promise.allSettled()等待所有 Promise 结束,无论成功或失败,返回所有结果
Promise.any()返回第一个成功的 Promise,如果全部失败,则返回 AggregateError
Promise.all([Promise.resolve("A"),Promise.resolve("B"),
]).then(console.log); // ["A", "B"]
5. async/await(Promise 的语法糖)
async function fetchData() {try {let data = await new Promise((resolve) => setTimeout(() => resolve("数据返回"), 1000));console.log(data); // 数据返回} catch (error) {console.error(error);}
}fetchData();

6.myAxios制作

基于 Promise 和 XHR 封装 myAxios 函数
核心语法:
function myAxios(config) {return new Promise((resolve, reject) => {// XHR 请求// 调用成功/失败的处理程序})
}myAxios({url: '目标资源地址'
}).then(result => {}).catch(error => {})
步骤:
 
  1. 定义 myAxios 函数,接收配置对象,返回 Promise 对象

  2. 发起 XHR 请求,默认请求方法为 GET

  3. 调用成功/失败的处理程序

  4. 使用 myAxios 函数,获取省份列表展示

整体代码:
function myAxios({ url, method = "GET", data = null, headers = {}, timeout = 5000 }) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open(method.toUpperCase(), url, true);xhr.timeout = timeout; // 设置超时时间// 设置请求头for (let key in headers) {xhr.setRequestHeader(key, headers[key]);}// 监听请求完成事件xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {try {const responseData = JSON.parse(xhr.responseText); // 解析 JSON 数据resolve(responseData);} catch (error) {reject("JSON 解析失败");}} else {reject(`请求失败,状态码:${xhr.status}`);}}};// 监听错误xhr.onerror = function () {reject("网络错误");};// 监听超时xhr.ontimeout = function () {reject("请求超时");};// 发送请求if (method.toUpperCase() === "GET" || data === null) {xhr.send();} else {xhr.setRequestHeader("Content-Type", "application/json");xhr.send(JSON.stringify(data));}});
}

同步代码和异步代码的区别

1. 同步代码(Synchronous)

同步代码按 顺序执行,当前任务完成后才执行下一个任务。如果某个任务耗时较长(如文件读取、网络请求等),整个程序都会被 阻塞

示例:
console.log("任务 1");
console.log("任务 2");
console.log("任务 3");

执行顺序:

任务 1
任务 2
任务 3

遇到阻塞的情况

console.log("开始");
for (let i = 0; i < 1e9; i++) {} // 模拟耗时操作
console.log("结束");

如果 for 循环运行了 3 秒,那么程序会 卡 3 秒,直到循环结束才继续执行后面的代码。


2. 异步代码(Asynchronous)

异步代码不会阻塞程序,它 不会等待任务完成,而是继续执行后续代码,等任务完成后再 通知(回调、Promise、async/await)

示例(setTimeout 异步执行):
console.log("任务 1");
setTimeout(() => console.log("任务 2(延迟 1 秒)"), 1000);
console.log("任务 3");

执行顺序:

任务 1
任务 3
任务 2(延迟 1 秒后执行)

👉 异步任务(setTimeout)不会阻塞后续代码的执行。


3. 常见的异步操作

  • 定时器(setTimeout, setInterval)
  • DOM 事件(click, input, scroll)
  • 网络请求(fetch, XMLHttpRequest, axios)
  • 文件读取(fs.readFile - Node.js)
  • 数据库操作(MongoDB, MySQL)
回调函数(Callback)
function fetchData(callback) {setTimeout(() => {callback("数据加载完成");}, 1000);
}console.log("开始请求数据");
fetchData((data) => console.log(data));
console.log("代码执行完毕");

执行顺序

开始请求数据
代码执行完毕
数据加载完成(1 秒后)

4. 现代异步方案

(1)Promise
开始请求数据
代码执行完毕
数据加载完成(1 秒后)

执行顺序

开始请求数据
代码执行完毕
数据加载完成(1 秒后)
(2)async/await
 
async function fetchData() {return new Promise((resolve) => {setTimeout(() => resolve("数据加载完成"), 1000);});
}async function main() {console.log("开始请求数据");let data = await fetchData();console.log(data);console.log("代码执行完毕");
}main();

执行顺序

开始请求数据
数据加载完成(1 秒后)
代码执行完毕

👉 await 让异步代码看起来像同步代码,增强可读性。


5. 总结

对比项同步代码异步代码
执行方式按顺序执行先执行后续代码,任务完成后再执行回调
是否阻塞是(遇到耗时任务会卡住)否(不会影响后续代码执行)
使用场景计算、变量赋值、DOM 操作等I/O 操作、网络请求、定时任务等
实现方式普通代码回调函数、Promise、async/await

Promise 链式调用

Promise.then() 方法会返回一个新的 Promise,这样就可以链式调用多个 .then(),实现 异步流程控制,避免回调地狱。

1. 基本链式调用

每个 .then() 处理上一个 .then() 返回的值:

new Promise((resolve) => {setTimeout(() => resolve(1), 1000); // 1秒后返回 1
}).then((num) => {console.log(num); // 1return num * 2;}).then((num) => {console.log(num); // 2return num * 3;}).then((num) => {console.log(num); // 6return num * 4;}).then(console.log); // 24

 ✅ 执行顺序

1
2
6
24

👉 每个 .then()

2. 链式调用处理异步操作

如果 .then() 返回一个 Promise,下一个 .then() 会等待这个 Promise 解析完成:

都返回一个新的值,供下一个 .then() 使用

new Promise((resolve) => {setTimeout(() => resolve("数据 1"), 1000);
}).then((data) => {console.log(data);return new Promise((resolve) => setTimeout(() => resolve("数据 2"), 1000));}).then((data) => {console.log(data);return new Promise((resolve) => setTimeout(() => resolve("数据 3"), 1000));}).then(console.log);

执行顺序(每步间隔 1 秒)

数据 1
数据 2
数据 3

👉 每个 .then() 返回一个 Promise,下一个 .then() 需等待前一个 Promise 解析完成

3. 处理异常

链式调用中,catch() 捕获前面所有 Promise 的错误:

new Promise((resolve, reject) => {setTimeout(() => reject("出错了!"), 1000);
}).then((data) => {console.log("不会执行", data);return "继续";}).catch((error) => {console.error("捕获错误:", error);return "错误已处理"; // catch() 可以返回新值}).then(console.log); // "错误已处理"

执行顺序

捕获错误: 出错了!
错误已处理

👉 catch() 捕获错误后,链式调用不会中断,后续 .then() 仍会执行

4. finally()

无论 Promise 成功或失败finally() 都会执行

new Promise((resolve, reject) => {setTimeout(() => reject("失败了"), 1000);
}).then(console.log).catch(console.error).finally(() => console.log("操作完成"));

 ✅ 执行顺序

失败了
操作完成

👉 finally() 适合做清理操作,比如关闭加载动画等

方法作用
.then()处理成功结果,可链式调用
.catch()处理 Promise 失败(捕获错误)
.finally()无论成功或失败都会执行

JavaScript 事件循环(Event Loop)

1. 什么是事件循环?

JavaScript 是 单线程 的,它使用 事件循环(Event Loop) 机制来执行同步和异步代码,确保不会阻塞主线程。

  • 同步任务:立即执行,放入 主线程(调用栈 Call Stack) 运行。
  • 异步任务:放入 任务队列(Task Queue),等主线程空闲后执行。

2. 事件循环执行流程

  1. 执行同步代码(放在主线程)。
  2. 遇到异步任务(如 setTimeoutPromisefetch,将它交给 Web APIs 处理。
  3. 同步代码执行完毕后,检查任务队列
    • 微任务队列(Microtask Queue):执行 Promise.then()queueMicrotask()MutationObserver
    • 宏任务队列(Macrotask Queue):执行 setTimeoutsetIntervalsetImmediate(Node.js)、I/O 任务等。
  4. 先执行所有微任务,再执行宏任务,然后进入下一个循环。

3. 示例解析

示例 1:基本事件循环
 
console.log("同步 1");setTimeout(() => console.log("setTimeout"), 0);Promise.resolve().then(() => console.log("Promise 1"));console.log("同步 2");

执行顺序

 
同步 1
同步 2
Promise 1  (微任务)
setTimeout  (宏任务)

📌 解释

  1. 同步 1、同步 2:立即执行。
  2. Promise微任务,优先执行。
  3. setTimeout宏任务,等微任务执行完才运行。

示例 2:多个宏任务和微任务
 
console.log("同步 1");setTimeout(() => console.log("setTimeout 1"), 0);
setTimeout(() => console.log("setTimeout 2"), 0);Promise.resolve().then(() => {console.log("Promise 1");return Promise.resolve();
}).then(() => console.log("Promise 2"));console.log("同步 2");

执行顺序

 
同步 1
同步 2
Promise 1  (微任务)
Promise 2  (微任务)
setTimeout 1  (宏任务)
setTimeout 2  (宏任务)

📌 解释

  1. 同步代码 先执行("同步 1" → "同步 2")。
  2. Promise 微任务 依次执行("Promise 1" → "Promise 2")。
  3. setTimeout 宏任务 最后执行("setTimeout 1" → "setTimeout 2")。

示例 3:复杂情况
 
console.log("A");setTimeout(() => {console.log("B");Promise.resolve().then(() => console.log("C"));
}, 0);Promise.resolve().then(() => console.log("D"));console.log("E");

执行顺序

 
A
E
D   (微任务)
B   (宏任务)
C   (B 里的微任务)

📌 解释

  1. 执行同步代码:"A"、"E"。
  2. Promise 微任务:"D" 先执行。
  3. setTimeout 宏任务:"B" 进入队列,等同步 & 微任务执行完毕后运行。
  4. "B" 里面的 Promise(C)微任务,执行优先级高于新的宏任务。

Promise.all() 静态方法

Promise.all() 用于 并行执行多个异步任务,并且 等待所有 Promise 都成功,才会返回 所有结果。如果 任何一个 Promise 失败Promise.all() 立即 reject,不会等待其他任务完成。

1. 基本用法

 
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);Promise.all([p1, p2, p3]).then((results) => {console.log(results); // [1, 2, 3]
});

执行顺序

 
[1, 2, 3]

📌 解释

  • Promise.all() 需要 等待所有 Promise 解析,返回 [1, 2, 3]

2. 异步任务示例

 
const p1 = new Promise((resolve) => setTimeout(() => resolve("数据 1"), 1000));
const p2 = new Promise((resolve) => setTimeout(() => resolve("数据 2"), 2000));
const p3 = new Promise((resolve) => setTimeout(() => resolve("数据 3"), 3000));console.log("开始请求");Promise.all([p1, p2, p3]).then((results) => {console.log("所有数据加载完成:", results);
});

执行顺序

 
开始请求
(等待 3 秒)
所有数据加载完成: [ '数据 1', '数据 2', '数据 3' ]

📌 解释

  • Promise.all() 等待所有任务完成(最大耗时任务 3 秒)。
  • 3 秒后,返回 ["数据 1", "数据 2", "数据 3"]

3. 处理失败(任何一个失败都会触发 reject)

 
const p1 = Promise.resolve("成功 1");
const p2 = Promise.reject("失败 2");
const p3 = Promise.resolve("成功 3");Promise.all([p1, p2, p3]).then(console.log).catch((error) => console.error("发生错误:", error));

执行顺序

 
发生错误: 失败 2

📌 解释

  • p2 失败,Promise.all 立即 reject,不会等待 p3

4. 结合 map() 批量请求

📌 批量请求 5 个 API

 
const urls = ["https://jsonplaceholder.typicode.com/todos/1","https://jsonplaceholder.typicode.com/todos/2","https://jsonplaceholder.typicode.com/todos/3",
];Promise.all(urls.map((url) => fetch(url).then((res) => res.json()))).then(console.log).catch(console.error);

执行结果

 
[{ "userId": 1, "id": 1, "title": "...", "completed": false },{ "userId": 1, "id": 2, "title": "...", "completed": false },{ "userId": 1, "id": 3, "title": "...", "completed": false }
]

📌 解释

  • map() 遍历 URL 数组,创建 fetch() 请求。
  • Promise.all() 并行执行所有请求,加速响应。

5. 解决 Promise.all() 失败问题

如果希望即使某些 Promise 失败,仍然获得结果,可以使用 Promise.allSettled()

 
const p1 = Promise.resolve("成功 1");
const p2 = Promise.reject("失败 2");
const p3 = Promise.resolve("成功 3");Promise.allSettled([p1, p2, p3]).then(console.log);

执行结果

 
[{ "status": "fulfilled", "value": "成功 1" },{ "status": "rejected", "reason": "失败 2" },{ "status": "fulfilled", "value": "成功 3" }
]

📌 解释

  • Promise.allSettled() 不会因为某个 Promise 失败而中断
  • 返回 每个 Promise 的状态(fulfilled / rejected)

总结

方法作用
Promise.all()全部成功才返回数组,任意失败立即 reject
Promise.allSettled()所有任务完成后返回数组(包含成功和失败)

 

医学、法律、商业、工程 都是崇高的追求,足以支撑人的一生。但诗歌、美丽、浪漫、爱情这些才是我们生活的意义。

相关文章:

《异步江湖:XHR、Promise 与 Event Loop 的恩怨情仇》

XMLHttpRequest XMLHttpRequest&#xff08;简称 XHR&#xff09;是浏览器提供的一个 JavaScript 对象&#xff0c;用于在客户端和服务器之间发送 HTTP 请求。它是实现 AJAX&#xff08;Asynchronous JavaScript and XML&#xff09; 技术的核心工具&#xff0c;允许网页在不…...

【极客时间】浏览器工作原理与实践-2 宏观视角下的浏览器 (6讲) - 2.5 渲染流程(上):HTML、CSS和JavaScript,是如何变成页面的?

https://time.geekbang.org/column/article/118205 2.5 渲染流程&#xff08;上&#xff09;&#xff1a;HTML、CSS和JavaScript&#xff0c;是如何变成页面的&#xff1f; 2.4讲了导航相关的流程&#xff0c;那导航被提交后又会怎么样呢&#xff1f; 就进入了渲染阶段。 这…...

蓝桥杯第15届真题解析

由硬件框图可以知道我们要配置LED 和按键、lcd&#xff0c;解决lcd引脚冲突 LED 先配置LED的八个引脚为GPIO_OutPut&#xff0c;锁存器PD2也是&#xff0c;然后都设置为起始高电平&#xff0c;生成代码时还要去解决引脚冲突问题 按键 按键配置&#xff0c;由原理图按键所对引…...

19c rac-expdp备份异常处理

客户反馈&#xff0c;有套19c rac环境&#xff0c;补丁是19.13的&#xff0c;有1个节点使用expdp备份用户异常&#xff0c;报错如下 Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production ORA-31626: job does not exist ORA-31637: cannot…...

轻松部署 Stable Diffusion WebUI 并实现局域网共享访问:解决 Conda Python 版本不为 3.10.6 的难题

这篇博文主要为大家讲解关于sd webui的部署问题&#xff0c;大家有什么不懂的可以随时问我&#xff0c;如果没有及时回复&#xff0c;可联系&#xff1a;1198965922 如果后续大家需要了解怎么用代码调用部署好的webui的接口&#xff0c;可以在评论区留言哦&#xff0c;博主可以…...

20250304在Ubuntu20.04的GUI下格式化exFAT格式的TF卡为ext4格式

20250304在Ubuntu20.04的GUI下格式化exFAT格式的TF卡为ext4格式 2025/3/4 16:47 缘起&#xff1a;128GB的TF卡&#xff0c;只能格式化为NTFS/exFAT/ext4。 在飞凌的OK3588-C下&#xff0c;NTFS格式只读。 exFAT需要改内核来支持。 现在只剩下ext4了。 linux R4默认不支持exFAT…...

AIP-159 跨集合读

编号159原文链接AIP-159: Reading across collections状态批准创建日期2019-07-26更新日期2019-07-26 有时&#xff0c;用户需要跨集合检索资源&#xff0c;或者在不知道资源所在集合的情况下检索单个资源。 指南 API 可以 在标准 List 方法中允许用户使用 - &#xff08;连…...

C++进阶(七)--STL--bitset(位图)的介绍与基本功能模拟实现

文章目录 引入1.位图的介绍1.1位图的概念1.2位图的应用1.3bitset的基本使用bitset的定义方式bitset成员函数的使用 2.位图的基本模拟实现2.1基本结构2.2构造函数2.3set函数2.4reset2.5test 3.位图考察题目3.1只出现⼀次的整数&#xff1f;3.2找到两个文件交集&#xff1f;3.3出…...

清北deepseek8本手册

“清北手册”通常是“清华大学和北京大学推出的DeepSeek手册”的简写。近期&#xff0c;随着AI技术的迅速发展&#xff0c;清北两高校陆续发布多本自家的DeepSeek学习手册&#xff0c;助力普通人学习进阶。 清华大学的DeepSeek手册已推出5册&#xff0c;内容丰富全面&#xff0…...

如何将Promise.then中的值直接return出来

Promise 如何返回值&#xff0c;而不是返回 Promise 对象。实际开发中使用封装好的异步请求函数&#xff0c;为什么调用该函数返回的值一直都是 undefined。 一、需求 定义一个 foo 函数&#xff0c;在里面执行异步操作&#xff0c;然后取得 Promise.then 中的值并 return 出来…...

利用golang embed特性嵌入前端资源问题解决

embed嵌入前端资源&#xff0c;配置前端路由的代码如下 func StartHttpService(port string, assetsFs embed.FS) error {//r : gin.Default()gin.SetMode(gin.ReleaseMode)r : gin.New()r.Use(CORSMiddleware())// 静态文件服务dist, err : fs.Sub(assetsFs, "assets/di…...

SPI驱动(二) -- SPI驱动程序模型

文章目录 参考资料&#xff1a;一、SPI驱动重要数据结构1.1 SPI控制器数据结构1.2 SPI设备数据结构1.3 SPI驱动数据结构 二、SPI 驱动框架2.1 SPI控制器驱动程序2.2 SPI设备驱动程序 三、总结 参考资料&#xff1a; 内核头文件&#xff1a;include\linux\spi\spi.h 一、SPI驱…...

【无标题】FrmImport

文章目录 前言一、问题描述二、解决方案三、软件开发&#xff08;源码&#xff09;四、项目展示五、资源链接 前言 我能抽象出整个世界&#xff0c;但是我不能抽象你。 想让你成为私有常量&#xff0c;这样外部函数就无法访问你。 又想让你成为全局常量&#xff0c;这样在我的…...

深入浅出 Go 语言:协程(Goroutine)详解

深入浅出 Go 语言&#xff1a;协程(Goroutine)详解 引言 Go 语言的协程&#xff08;goroutine&#xff09;是其并发模型的核心特性之一。协程允许你轻松地编写并发代码&#xff0c;而不需要复杂的线程管理和锁机制。通过协程&#xff0c;你可以同时执行多个任务&#xff0c;并…...

vLLM代码推理Qwen2-VL多模态

由于近期代码微调以及测试都是在远程服务器上&#xff0c;因此LLamafactory-cli webui 以及vLLM的ui均无法使用&#xff0c;因此不断寻求解决方案&#xff0c;我提供一个解决方案&#xff0c;LLamafactory微调完成的模型需要合并为一个完整模型后再使用vLLM进行代码推理测试微调…...

DNS云解析有什么独特之处?

在数字化浪潮中&#xff0c;每一次网页点击、视频加载或在线交易背后&#xff0c;都依赖着域名系统&#xff08;DNS&#xff09;的高效运转。传统DNS架构的局限性&#xff08;如单点故障、延迟高、安全脆弱&#xff09;在云计算时代被彻底颠覆&#xff0c;DNS云解析作为新一代解…...

视频流畅播放相关因素

视频播放的流畅度是一个综合性问题&#xff0c;涉及从视频文件本身到硬件性能、网络环境、软件优化等多个环节。以下是影响流畅度的关键因素及优化建议&#xff1a; 一、视频文件本身 1. 分辨率与帧率 1.问题&#xff1a;高分辨率&#xff08;如4K&#xff09;或高帧率&#…...

Python实现一个类似MybatisPlus的简易SQL注解

文章目录 前言实现思路定义一个类然后开始手撸这个微型框架根据字符串获取到所定义的DTO类构建返回结果装饰器解析字符串&#xff0c;获得变量SQL字符串拼接 使用装饰器 前言 在实际开发中&#xff0c;根据业务拼接SQL所需要考虑的内容太多了。于是&#xff0c;有没有一种办法…...

linux一些使用技巧

linux一些使用技巧 文件名称和路径的提取切换用户执行当前脚本一行演示单引号与双引号的使用curl命令仅输出响应头信息,不输出body体文件名称和路径的提取 文件路径为 /tmp/tkgup/test.sh 方式获取文件名获取文件路径获取文件全路径方式一basename ${file}dirname ${file}real…...

小模型和小数据可以实现AGI吗

小模型和小数据很难实现真正的 通用人工智能&#xff08;AGI, Artificial General Intelligence&#xff09;&#xff0c;但在特定任务或受限环境下&#xff0c;可以通过高效的算法和优化方法实现“近似 AGI” 的能力。 1. 为什么小模型小数据难以实现 AGI&#xff1f; AGI 需…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...