axios和fetch的实现原理以及区别,与XMLHttpRequest的关系,并结合react封装统一请求示例
Axios 和 Fetch 对比及统一请求封装
1. Axios 基础用法
1.1 安装和引入
// 安装
npm install axios// 引入
import axios from 'axios';
1.2 基本请求方法
// GET 请求
axios.get('/api/users').then(response => console.log(response.data)).catch(error => console.error(error));// POST 请求
axios.post('/api/users', {name: 'John',age: 30
}).then(response => console.log(response.data)).catch(error => console.error(error));// PUT 请求
axios.put('/api/users/1', {name: 'John',age: 31
});// DELETE 请求
axios.delete('/api/users/1');// 使用 async/await
async function fetchData() {try {const response = await axios.get('/api/users');console.log(response.data);} catch (error) {console.error(error);}
}
1.3 配置选项
// 全局配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer token';
axios.defaults.timeout = 5000;// 请求配置
axios({method: 'post',url: '/api/users',data: {name: 'John',age: 30},headers: {'Content-Type': 'application/json'},timeout: 5000,withCredentials: true
});// 创建实例
const instance = axios.create({baseURL: 'https://api.example.com',timeout: 5000,headers: {'X-Custom-Header': 'value'}
});
2. Fetch 基础用法
2.1 基本请求方法
// GET 请求
fetch('/api/users').then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));// POST 请求
fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({name: 'John',age: 30})
}).then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));// 使用 async/await
async function fetchData() {try {const response = await fetch('/api/users');const data = await response.json();console.log(data);} catch (error) {console.error(error);}
}
2.2 请求配置
fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json','Authorization': 'Bearer token'},body: JSON.stringify(data),mode: 'cors',credentials: 'include',cache: 'no-cache',redirect: 'follow'
});
3. Axios 和 Fetch 的主要区别
3.1 功能差异
- 请求/响应拦截
// Axios 支持拦截器
axios.interceptors.request.use(config => {// 请求前处理return config;
}, error => {return Promise.reject(error);
});axios.interceptors.response.use(response => {// 响应后处理return response;
}, error => {return Promise.reject(error);
});// Fetch 需要自行封装
const fetchWithInterceptor = async (...args) => {// 请求前处理const response = await fetch(...args);// 响应后处理return response;
};
- 自动转换 JSON
// Axios 自动转换 JSON
axios.get('/api/users').then(response => console.log(response.data)); // 直接获取数据// Fetch 需要手动转换
fetch('/api/users').then(response => response.json()).then(data => console.log(data));
- 错误处理
// Axios 统一处理错误
axios.get('/api/users').catch(error => {if (error.response) {// 服务器响应错误console.log(error.response.status);} else if (error.request) {// 请求未收到响应console.log(error.request);} else {// 请求配置错误console.log(error.message);}});// Fetch 需要手动检查状态
fetch('/api/users').then(response => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}return response.json();}).catch(error => console.log(error));
3.2 浏览器支持
- Fetch: 现代浏览器原生支持,但不支持 IE
- Axios: 支持所有主流浏览器,包括 IE11
4. React 统一请求封装
4.1 基于 Axios 的封装
// src/utils/request.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { message } from 'antd';// 请求配置类型
interface RequestConfig extends AxiosRequestConfig {loading?: boolean;skipErrorHandler?: boolean;
}// 响应数据类型
interface ResponseData<T = any> {code: number;data: T;message: string;
}class Request {private instance: AxiosInstance;private loading: boolean;constructor() {this.instance = axios.create({baseURL: process.env.REACT_APP_API_URL,timeout: 10000,headers: {'Content-Type': 'application/json'}});this.loading = false;this.setupInterceptors();}private setupInterceptors() {// 请求拦截器this.instance.interceptors.request.use((config: RequestConfig) => {// 添加 tokenconst token = localStorage.getItem('token');if (token) {config.headers.Authorization = `Bearer ${token}`;}// 显示加载状态if (config.loading) {this.loading = true;// 可以使用 antd 的 loading 组件}return config;},error => {return Promise.reject(error);});// 响应拦截器this.instance.interceptors.response.use((response: AxiosResponse<ResponseData>) => {// 隐藏加载状态this.loading = false;const { code, data, message: msg } = response.data;// 处理业务错误if (code !== 0) {if (!response.config.skipErrorHandler) {message.error(msg || '请求失败');}return Promise.reject(new Error(msg || '请求失败'));}return data;},error => {// 隐藏加载状态this.loading = false;// 处理 HTTP 错误if (!error.config?.skipErrorHandler) {if (error.response) {switch (error.response.status) {case 401:message.error('未授权,请重新登录');// 可以在这里处理登出逻辑break;case 403:message.error('拒绝访问');break;case 404:message.error('请求的资源不存在');break;case 500:message.error('服务器错误');break;default:message.error(`请求失败: ${error.message}`);}} else {message.error('网络错误,请检查网络连接');}}return Promise.reject(error);});}// 通用请求方法public async request<T = any>(config: RequestConfig): Promise<T> {try {const response = await this.instance.request<any, T>(config);return response;} catch (error) {return Promise.reject(error);}}// GET 请求public get<T = any>(url: string, config?: RequestConfig): Promise<T> {return this.request({ ...config, method: 'GET', url });}// POST 请求public post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {return this.request({ ...config, method: 'POST', url, data });}// PUT 请求public put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {return this.request({ ...config, method: 'PUT', url, data });}// DELETE 请求public delete<T = any>(url: string, config?: RequestConfig): Promise<T> {return this.request({ ...config, method: 'DELETE', url });}
}export default new Request();
4.2 使用示例
// src/api/user.ts
import request from '@/utils/request';interface User {id: number;name: string;age: number;
}export const userApi = {// 获取用户列表getUsers: () => request.get<User[]>('/api/users'),// 获取用户详情getUser: (id: number) => request.get<User>(`/api/users/${id}`),// 创建用户createUser: (data: Omit<User, 'id'>) => request.post<User>('/api/users', data),// 更新用户updateUser: (id: number, data: Partial<User>) =>request.put<User>(`/api/users/${id}`, data),// 删除用户deleteUser: (id: number) =>request.delete(`/api/users/${id}`)
};// 在组件中使用
import React, { useEffect, useState } from 'react';
import { userApi } from '@/api/user';const UserList: React.FC = () => {const [users, setUsers] = useState<User[]>([]);useEffect(() => {const fetchUsers = async () => {try {const data = await userApi.getUsers();setUsers(data);} catch (error) {console.error('Failed to fetch users:', error);}};fetchUsers();}, []);const handleCreateUser = async () => {try {const newUser = await userApi.createUser({name: 'John',age: 30});setUsers(prev => [...prev, newUser]);} catch (error) {console.error('Failed to create user:', error);}};return (<div>{/* 渲染用户列表 */}</div>);
};export default UserList;
5. 最佳实践建议
1. 选择建议
- 小型项目:使用 Fetch 足够
- 大型项目:推荐使用 Axios(功能更完善)
- 需要兼容 IE:必须使用 Axios
2. 性能优化
- 合理使用请求取消
- 实现请求缓存
- 避免重复请求
3. 安全考虑
- 统一处理敏感信息
- 实现请求超时
- CSRF 防护
4. 开发建议
- 使用 TypeScript 增加类型安全
- 集中管理 API 请求
- 做好错误处理
- 添加请求日志
6. fetch实现原理
fetch 是一种用于在浏览器中发起 HTTP 请求并获取响应的 API,它是 XMLHttpRequest 的现代替代品。fetch 基于 Promise,使得异步代码更加简洁和易于理解。它的实现原理是利用浏览器提供的低级 API 来执行 HTTP 请求和处理响应。
1. fetch 的基本使用
fetch 接口允许你通过网络发起请求并返回响应,它的基本语法如下:
fetch(url, options).then(response => response.json()) // 或者 response.text(), response.blob() 等.then(data => console.log(data)).catch(error => console.log(error));
url:要请求的资源地址。
options(可选):一个包含配置选项的对象,用于配置请求方法、请求头、请求体等。
2. fetch 的底层实现原理
fetch 是基于浏览器的 Fetch API 实现的,它的实现原理依赖于以下几个关键步骤:
2.1 发起 HTTP 请求
当你调用 fetch 时,浏览器通过 HTTP 协议 向目标 URL 发送请求。这个请求可以是 GET、POST、PUT 等类型,并且可以包含请求头和请求体(例如,POST 请求通常包含数据)。
在底层,fetch 会使用 浏览器的网络栈(例如,TCP/IP 协议、TLS/SSL 等)通过 DNS 查询目标服务器的 IP 地址,建立网络连接,并发送 HTTP 请求。
2.2 异步请求与 Promise
fetch 是基于 Promise 的,它允许我们在请求完成后异步处理结果。这意味着当你调用 fetch 时,浏览器会立即发起请求并返回一个未完成的 Promise。then 方法中传入的回调函数会在请求完成时被调用,而 catch 会捕获任何可能发生的错误。
例如:
fetch(url) // 发起请求并返回一个 Promise.then(response => {console.log("Response received");return response.json(); // 解析 JSON 数据}).catch(error => console.log(error)); // 捕获错误
在浏览器中,fetch 实际上是通过 JavaScript 事件循环机制调度 HTTP 请求,它不会阻塞主线程。由于 fetch 是异步的,它允许页面在等待请求返回的同时执行其他任务。
2.3 请求头与配置
在 fetch 请求中,你可以通过 options 对象来配置请求。例如,你可以设置请求方法(GET、POST 等),设置请求头,发送请求体等。
const options = {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ key: 'value' }) // 请求体
};fetch(url, options).then(response => response.json()).then(data => console.log(data)).catch(error => console.log(error));
这些选项会通过浏览器的 HTTP 客户端 发送到服务器。浏览器会根据请求的类型和配置,构建相应的 HTTP 请求头部和请求体。
2.4 响应处理
fetch 发起请求并接收响应时,它返回的 response 对象代表 HTTP 响应。这些响应信息包括状态码、响应头和响应体内容。
fetch(url).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json(); // 返回 JSON 数据}).then(data => console.log(data)).catch(error => console.log(error));
response.ok 是一个布尔值,表示响应是否成功(状态码 200 到 299 表示成功)。response.json()、response.text()、response.blob() 等方法允许你读取响应体内容。
2.5 CORS(跨域资源共享)
当你发起跨域请求时,浏览器会处理跨域资源共享(CORS)问题。fetch 会自动处理 预检请求(OPTIONS 请求),并根据目标服务器的 CORS 策略决定是否允许访问。
如果服务器响应了正确的 CORS 头部,浏览器会允许访问并返回资源。
如果服务器未响应适当的 CORS 头部,fetch 请求将被阻止,并抛出一个错误。
3. 底层实现
从实现角度来看,fetch 依赖于浏览器内部的网络通信堆栈。以下是 fetch 实现的几个关键点:
请求建立:
当 fetch 被调用时,浏览器会通过其网络库(如 libcurl 或原生的浏览器网络栈)解析 URL、进行 DNS 查询、建立 TCP 连接。
发送请求:
浏览器根据配置(如请求方法、头部、体等)构造 HTTP 请求并发送到目标服务器。
等待响应:
请求发送后,浏览器会等待响应。浏览器根据响应的 HTTP 状态码和头部信息来判断请求是否成功。
解析响应:
浏览器收到响应后,会将响应内容存储在 response 对象中,并提供如 response.json()、response.text() 等方法来解析响应内容。
事件循环和 Promise:
fetch 的操作是异步的,基于 事件循环 机制和 Promise。当响应可用时,相关的 .then() 或 .catch() 方法会被执行。
4. 与 XMLHttpRequest 的对比
fetch 与传统的 XMLHttpRequest (XHR) 相比,有以下几个主要优势:
Promise 支持:fetch 基于 Promise,使得代码更加简洁和易于理解,避免了回调地狱。
简洁的 API:fetch 的 API 更加简洁,尤其是在处理响应体时。你只需要使用 .json()、.text()、.blob() 等方法来解析响应内容,而 XMLHttpRequest 需要更多的手动配置。
默认不发送 Cookies:fetch 默认不会发送跨域请求时的 Cookies(除非配置了 credentials 选项)。而 XMLHttpRequest 默认会自动发送 Cookies。
支持流式传输:fetch 支持响应流(ReadableStream),允许更高效地处理大文件和流式响应。
5. 总结
fetch 是现代浏览器中用来发起 HTTP 请求的原生 API,它依赖浏览器的网络堆栈来执行低级别的请求操作。通过基于 Promise 的设计,fetch 提供了更清晰的异步操作流程。它的实现利用了浏览器的网络层和异步编程机制,能够有效处理 HTTP 请求、响应、CORS 等问题。
7. fetch和XMLHttpRequest区别
fetch 和 XMLHttpRequest 都是浏览器提供的用于发起 HTTP 请求的 API,尽管它们的目的相同——发送和接收数据——它们在设计、功能、使用方式和底层实现上有许多差异。下面是它们之间的关系和主要区别:
1. 关系:
功能相似:fetch 和 XMLHttpRequest 都用于从客户端(浏览器)发送 HTTP 请求到服务器,并获取响应。这意味着它们都可以用来发送数据(如表单提交、获取 API 数据等)。
底层原理:虽然 fetch 是现代浏览器的标准 API,而 XMLHttpRequest 是较旧的标准 API,但它们都通过浏览器的网络堆栈与服务器通信。fetch 是 XMLHttpRequest 的替代品,提供了更现代、更简洁的 API。
异步操作:fetch 和 XMLHttpRequest 都是异步的,可以执行异步 HTTP 请求,但 fetch 使用了更现代的 Promise 机制,而 XMLHttpRequest 主要基于回调(callback)机制。
2. 主要区别:
2.1 API 风格和易用性
fetch:
基于 Promise,支持链式调用,使代码更加简洁和易于维护。
语法简洁,只返回响应的 response 对象,不会自动处理请求错误(需要手动检查状态码和抛出错误)。
采用更现代的设计,支持 async/await,使得处理异步操作更自然。
示例:
fetch(url).then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));
XMLHttpRequest:
基于回调机制,使用 onreadystatechange 或 onload 事件处理响应,导致代码更复杂,容易出现回调地狱(callback hell)。
没有内置的 Promise 支持,因此通常与回调函数或外部库(如 jQuery)一起使用来简化操作。
示例:
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {const data = JSON.parse(xhr.responseText);console.log(data);}
};
xhr.send();
2.2 请求和响应的处理
fetch:
返回的是一个 Promise,这意味着响应是异步处理的,并且通过 then() 或 async/await 进行响应数据的处理。
不会自动抛出 HTTP 错误(如 404 或 500),需要手动检查 response.ok 或 response.status 来判断请求是否成功。
XMLHttpRequest:
使用事件回调处理响应,通常是通过 onload 或 onreadystatechange 来处理请求的响应。
自动将响应文本(responseText)作为字符串返回,解析 JSON 或其他数据类型需要手动处理。
XMLHttpRequest 会自动在请求失败时调用 onerror 回调函数。
2.3 错误处理
fetch:
默认不会对 HTTP 错误(如 404、500)抛出错误,只有网络错误(例如无网络连接)才会触发 .catch()。
需要手动检查 response.ok 或 response.status 来判断响应是否成功。
示例:
fetch(url).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json();}).then(data => console.log(data)).catch(error => console.error('Fetch error:', error));
XMLHttpRequest:
XMLHttpRequest 会根据请求的状态码来执行相应的回调方法,通常是通过检查 xhr.status 来判断请求是否成功。
2.4 请求体处理
fetch:
直接支持通过 body 选项发送请求体(如发送 JSON 数据),且支持 FormData、Blob、ArrayBuffer 等多种数据类型。
通过 headers 选项配置请求头。
示例:
const options = {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ key: 'value' })
};fetch(url, options).then(response => response.json()).then(data => console.log(data));
XMLHttpRequest:
需要手动设置请求头,并使用 xhr.send() 发送请求体。
对发送 JSON 数据通常需要手动字符串化,并设置 Content-Type 头部。
示例:
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ key: 'value' }));
2.5 跨域请求(CORS)
fetch:
默认支持跨域请求(CORS),但需要服务器在响应中包含适当的 CORS 头部。
可以通过 credentials 选项来控制是否发送 Cookies、授权头等。
示例:
fetch(url, { credentials: 'same-origin' }).then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));
XMLHttpRequest:
支持跨域请求,但需要手动处理 CORS(通常在跨域时需要服务器添加 CORS 头部)。
默认发送跨域请求时不会携带 Cookies。
2.6 流式响应(Streams)
fetch:
支持流式响应,允许逐步处理大文件或大数据集。响应体是一个 ReadableStream,这使得你可以逐步读取数据而不是一次性获取整个响应。
示例:
fetch(url).then(response => {const reader = response.body.getReader();reader.read().then(function processText({ done, value }) {if (done) return;console.log(value);reader.read().then(processText);});});
XMLHttpRequest:
不支持流式响应。它需要等待整个响应下载完毕才会调用回调函数。
2.7 支持情况
fetch:
fetch 是一个现代的 API,已被大多数现代浏览器(如 Chrome、Firefox、Edge、Safari)支持,但在一些旧版本的浏览器中(如 Internet Explorer)不支持。
需要通过 polyfill 来在不支持的浏览器中使用。
XMLHttpRequest:
XMLHttpRequest 在所有主流浏览器中都被广泛支持,包括旧版本的浏览器(如 Internet Explorer)。
3. 总结
fetch 是一个现代的、基于 Promise 的 API,具有更简洁的语法和更强大的功能,如流式响应、异步操作的简化、更易于使用的错误处理等。
XMLHttpRequest 是较老的 API,基于回调机制,功能上不如 fetch 灵活和简洁,但仍然被广泛使用,特别是在一些较旧的浏览器中。
尽管 fetch 是 XMLHttpRequest 的现代替代品,XMLHttpRequest 仍然存在于许多遗留的代码中。fetch 是未来的主流选择,而 XMLHttpRequest 在许多场景下也依然可用,尤其是与旧版本的浏览器兼容时。
8. Axios的实现原理
Axios 是一个基于 Promise 的 JavaScript 库,用于简化浏览器和 Node.js 环境中的 HTTP 请求。Axios 主要通过封装 XMLHttpRequest 或 Node.js 的 http/https 模块 来实现对 HTTP 请求的支持,而 并没有直接封装 fetch。
1. 浏览器中的实现
在 浏览器环境 中,Axios 默认使用 XMLHttpRequest 进行 HTTP 请求。XMLHttpRequest 是浏览器中较早的一个用于发起 HTTP 请求的 API,广泛支持,并且可以处理浏览器中常见的 HTTP 请求需求。
使用 XMLHttpRequest:
在浏览器环境中,Axios 封装了 XMLHttpRequest,对其进行了改造和增强,使得 API 使用更加简洁。
通过封装,Axios 提供了基于 Promise 的异步编程模型,支持链式调用、请求和响应拦截、请求取消、自动转换 JSON 数据等功能。
Axios 还会自动处理一些常见的错误情况(如 404、500 错误)并通过 Promise 抛出异常,方便开发者统一处理。
示例:Axios 在浏览器中的基本实现(简化版)
// 伪代码,简化版
function axiosRequest(config) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open(config.method, config.url, true);// 设置请求头Object.keys(config.headers).forEach(key => {xhr.setRequestHeader(key, config.headers[key]);});xhr.onload = function () {if (xhr.status >= 200 && xhr.status < 300) {resolve(xhr.response); // 请求成功,解析响应} else {reject(new Error('Request failed with status code ' + xhr.status)); // 请求失败}};xhr.onerror = function () {reject(new Error('Network Error')); // 网络错误};// 发送请求xhr.send(config.data);});
}
2. Node.js 中的实现
在 Node.js 环境 中,Axios 不是使用 XMLHttpRequest,因为 XMLHttpRequest 是浏览器专有的 API,而是使用 Node.js 原生的 http 和 https 模块 来发起 HTTP 请求。
使用 http/https 模块:
在 Node.js 中,Axios 使用 Node.js 自带的 HTTP 库 (http 或 https),这些库非常适合用于服务器端请求。
Axios 将 HTTP 请求和响应处理的过程封装为 Promise,允许开发者通过链式调用来处理异步操作。
示例:Axios 在 Node.js 中的基本实现(简化版)
// 伪代码,简化版
const http = require('http');
const https = require('https');function axiosRequest(config) {return new Promise((resolve, reject) => {const client = config.url.startsWith('https') ? https : http;const req = client.request(config.url, { method: config.method, headers: config.headers }, (res) => {let data = '';// 接收数据res.on('data', chunk => {data += chunk;});res.on('end', () => {if (res.statusCode >= 200 && res.statusCode < 300) {resolve(data); // 请求成功,解析响应} else {reject(new Error('Request failed with status code ' + res.statusCode)); // 请求失败}});});req.on('error', (e) => {reject(e); // 网络错误});// 发送请求req.write(config.data);req.end();});
}
3. Axios 与 fetch 的关系
Axios 和 fetch 都是基于 Promise 的异步 API,功能上有很多相似之处,例如:
都支持发起 GET、POST 等 HTTP 请求。
都支持 Promise,允许链式调用。
都允许设置请求头、请求体、超时等配置。
然而,Axios 并没有直接基于 fetch 封装。虽然 fetch 是现代浏览器中用于发起 HTTP 请求的推荐 API,Axios 仍然选择使用 XMLHttpRequest 在浏览器中发起请求,原因如下:
更广泛的兼容性:XMLHttpRequest 在较旧的浏览器中也有很好的支持,尤其是在像 Internet Explorer 这样的旧版浏览器中。fetch 相对较新,部分旧浏览器不支持,需要 polyfill 来补充支持。
功能扩展:Axios 提供了一些 fetch 不直接支持的功能,比如请求拦截器、响应拦截器、自动转换 JSON 数据、请求取消、默认超时处理等。
简化错误处理:fetch 本身不会自动抛出 HTTP 错误(如 404 或 500 错误),需要开发者手动检查 response.ok。而 Axios 会根据 HTTP 状态码自动抛出异常,简化了错误处理。
4. 总结
Axios 的实现原理:Axios 在 浏览器中使用 XMLHttpRequest,在 Node.js 中使用 http 或 https 模块 来发起 HTTP 请求。
Axios 并没有封装 fetch,尽管它与 fetch 有一些相似之处。Axios 提供了更多的功能(如请求拦截、响应拦截、自动 JSON 转换等),并选择了在浏览器中使用 XMLHttpRequest 来确保更广泛的兼容性。
相关文章:
axios和fetch的实现原理以及区别,与XMLHttpRequest的关系,并结合react封装统一请求示例
Axios 和 Fetch 对比及统一请求封装 1. Axios 基础用法 1.1 安装和引入 // 安装 npm install axios// 引入 import axios from axios;1.2 基本请求方法 // GET 请求 axios.get(/api/users).then(response > console.log(response.data)).catch(error > console.error…...
2024年阅读书单
《高效能人士的7个习惯》 史蒂芬.柯维 精进 《高效能人士的7个习惯》在读了一遍之后,记住非常深刻的就是积极主动和以终为始。 《软件架构》 Simon Brown 架构、技术 《软件架构》这本书比较抽象,若是工作时间比较少的人来读,可能觉得作者没写…...
Eclipse 内容辅助
Eclipse的内容辅助(Content Assist)功能是一项核心特性,它通过提供代码提示和自动完成建议来提高开发效率。这个功能能够在用户编写代码时自动显示可能的代码补全选项,如变量名、方法名、类名和关键字等。它还能根据用户的输入和上…...
【数学建模笔记】评价模型-基于熵权法的TOPSIS模型
视频课地址:https://www.bilibili.com/video/BV1eRyVYUEhg 本系列文章和课程一样,只使用Python实现,好久没玩数学建模了 国赛中不能再用TOPSIS,可以做辅助算法。 1. 算法原理 熵权TOPSIS方法是一种结合熵权法和TOPSIS的决策分析…...
小程序发版后,强制更新为最新版本
为什么要强制更新为最新版本? 在小程序的开发和运营过程中,强制用户更新到最新版本是一项重要的策略,能够有效提升用户体验并保障系统的稳定性与安全性。以下是一些主要原因: 1. 功能兼容 新功能或服务通常需要最新版本的支持&…...
数据分析思维(七):分析方法——群组分析方法
数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python,更重要的是数据分析思维。没有数据分析思维和业务知识,就算拿到一堆数据,也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》,本文内容就是提取…...
SAP 01-初识AMDP(ABAP-Managed Database Procedure)
1. 什么是AMDP(ABAP-Managed Database Procedure) 1.)AMDP - ABAP管理数据库程序,是一种程序,我们可以使用SQLSCRIPT在AMDP内部编写代码,SQLSCRIPT是一种与SQL脚本相同的数据库语言,这种语言易于理解和编码。 将AM…...
.net core 线程锁,互斥锁,自旋锁,混合锁
线程锁、互斥锁、自旋锁和混合锁是多线程编程中的重要概念,它们用于控制对共享资源的访问,避免数据竞争和不一致性。每种锁有其特定的适用场景和特点。我们来逐一解释它们,并进行比较。 1. 线程锁(Thread Lock) 线程…...
大数据系列之:深入理解学习使用腾讯COS和COS Ranger权限体系解决方案,从hdfs同步数据到cos
大数据系列之:深入理解学习使用腾讯COS和COS Ranger权限体系解决方案,从hdfs同步数据到cos 对象存储COS对象存储基本概念COS Ranger权限体系解决方案部署组件COS Ranger Plugin部署COS-Ranger-Service部署COS Ranger Client部署 COSN 从hdfs同步数据到co…...
Uniapp Android 本地离线打包(详细流程)
一、简介 App 离线 SDK 暂时不支持 Kotlin,未来不清楚。 uniapp 提供了 云打包 与 本地打包 两种方案,云打包 需要排队且还有次数限制,本地打包 则就没有这些限制,而且会 本地打包 对开发 原生插件 有很大的帮助。 细节&#x…...
单片机常用外设开发流程(1)(IMX6ULL为例)
1.通过GPIO引脚控制led灯和key按钮 (1)设置多路复用的引脚(SW_MUX_CTL)也可以说是选择让引脚以哪种工作模式工作 (2)设置电器属性(SW_PAD_CTL)上拉、等等... (3)设置GPIO的方向&am…...
机器学习 学习知识点
机器学习 学习知识点 什么是消融实验(Ablation experiment)?num_step与batch_size的区别python glob.glob()函数认识python的条件判断之is not、is not None、is Nonetqdm介绍及常用方法softmax 激活函数。type_as(tesnor)Python OpenCV cv2.…...
深入了解PINN:物理信息神经网络(Physics-Informed Neural Networks)
1. 什么是PINN(物理信息神经网络)? 物理信息神经网络(PINN,Physics-Informed Neural Networks)是一类通过结合神经网络和物理方程的深度学习方法。其主要特点是将物理系统的约束条件(如偏微分方…...
人工智能知识分享第八天-机器学习_泰坦尼克生存预估线性回归和决策树回归对比案例
泰坦尼克生存预估案例 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import classification_report import matplotlib.pyplot as plt from sklearn.tree import plot_t…...
封装/前线修饰符/Idea项目结构/package/impore
目录 1. 封装的情景引入 2. 封装的体现 3. 权限修饰符 4. Idea 项目结构 5. package 关键字 6. import 关键字 7. 练习 程序设计:高内聚,低耦合; 高内聚:将类的内部操作“隐藏”起来,不需要外界干涉;…...
python中的装饰器
装饰器(Decorator)是 Python 中的一种语法糖,它允许你修改或增强函数或类的行为。下面详细解释: 基本概念 装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数: def my_decor…...
HTMLElement、customElements及元素拓展
文章目录 HTMLElement 与 customElementscustomElements.define() 方法说明HTML 元素方法拓展 HTMLElement 与 customElements HTMLElement 概述 HTMLElement是一个接口,它表示所有HTML元素。几乎所有的HTML标签(如<div>、<p>、<a>等…...
字玩FontPlayer开发笔记3 性能优化 大量canvas渲染卡顿问题
字玩FontPlayer开发笔记3 性能优化 大量canvas渲染卡顿问题 字玩FontPlayer是笔者开源的一款字体设计工具,使用Vue3 ElementUI开发,源代码: github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontpl…...
PyTorch 中 coalesce() 函数详解与应用示例
PyTorch 中 coalesce() 函数详解与应用示例 coalesce: 美 [ˌkoʊəˈlɛs] 合并;凝聚;联结,注意发音 引言 在 PyTorch 中,稀疏张量(Sparse Tensor)是一种高效存储和操作稀疏数据的方式。稀疏…...
计算机网络(第8版)第3章课后习题--透明传输
【3-11】 试分别讨论以下各种情况在什么条件下是透明传输,在什么条件下不是透明传 输。(提示:请弄清什么是“透明传输”,然后考虑能否满足其条件。) (1)普通的电话通信。 (2)互联网提供的电子邮件服务。 解 答 : 透明传输是指在数据传输…...
JavaScript 日期格式
在 JavaScript 中,日期格式可以通过 Date 对象进行操作和格式化。下面是一些常见的 JavaScript 日期格式及其示例: 1. ISO 8601 格式 ISO 8601 是一种标准的日期和时间表示方法,格式为 YYYY-MM-DDTHH:mm:ss.sssZ,例如: let date = new Date(); console.log(date.toISOS…...
云打印之拼多多打印组件交互协议
拼多多打印组件交互协议相关介绍如下: 1、打印组件下载地址 http://meta.pinduoduo.com/api/one/app/v1/lateststable?appIdcom.xunmeng.pddprint&platformwindows&subTypemain 2、socket连接端口 如果是http的话,端口是5000 socket new …...
Oracle数据库如何找到 Top Hard Parsing SQL 语句?
有一个数据库应用程序存在过多的解析问题,因此需要找到产生大量硬解析的主要语句。 什么是硬解析 Oracle数据库中的硬解析(Hard Parse)是指在执行SQL语句时,数据库需要重新解析该SQL语句,并创建新的执行计划的过程。这…...
浅谈棋牌游戏开发流程二:后端技术选型与基础环境搭建
一、前言:客户端只是台前,后端才是幕后“指挥中心” 在上一篇“客户端技术”中,我们聊到玩家看到的一切动作、动画、界面逻辑,都靠客户端去渲染和交互。但若没有后端的支撑,玩家点了“出牌”可能就像一拳打在空气里—…...
使用qiankun搭建微前端应用及踩坑
线上演示地址:React App 源码地址:https://github.com/Jiang-K-J/micro-app?tabreadme-ov-file (帮忙点个小星星) 主应用:react 18 子应用:vite vue3 子应用:react 18 安装 主应用 $ y…...
Windows 环境配置 HTTPS 服务实战
一、 环境准备 win10以上操作系统安装 Certbot申请阿里云\腾讯云域名安装 nginx 1.3以上版本 二、Certbot 安装及 SSL 证书生成 Certbot 是一个免费、开源工具,用于自动化在Web服务器上获取和更新SSL/TLS证书。它可以通过Let’s Encrypt服务获取免费的SSL/TLS证书…...
小程序租赁系统开发的优势与应用前景分析
内容概要 小程序租赁系统是一种新兴的数字化解决方案,旨在为用户提供更加便捷与高效的租赁服务。它通常包括一系列功能,如在线浏览、即时预定、支付功能以及用户反馈机制。这些系统在使用上极为友好,让用户能够轻松选择所需的商品或服务&…...
Redis(基础篇 + 实践篇 )
01 | 基本架构:一个键值数据库包含什么? Redis 作为一个内存数据存储系统,它的架构设计非常简洁,但功能非常强大。理解其核心架构对高效使用 Redis 至关重要。 客户端与服务器架构: 客户端通过 TCP 协议连接到 Redis …...
单片机-独立按键矩阵按键实验
1、按键介绍 按键管脚两端距离长的表示默认是导通状态,距离短的默认是断开状态, 如果按键按下,初始导通状态变为断开,初始断开状态变为导通 我们开发板是采用软件消抖,一般来说一个简单的按键消抖就是先读取按键的状…...
我用AI学Android Jetpack Compose之入门篇(1)
这篇我们先来跑通第一个Android Jetpack Compose工程,现在新版本的Android Studio,新建工程选择Empty Activity默认就会开启Jetpack Compose的支持,再次声明,答案来自 通义千问Ai 文章目录 1.用Android Jetpack Compose需要安装什…...
简单的生产数据库重连策略优化
简单的druid生产数据库重连策略优化 1. 需求 我们生产环境有一次在大量请求拥堵后,好多数据库操作都超时了,在此之后数据库的连接池不能正常的获取数据库连接了,我们确认了数据库服务是没有问题的,那么就是连接池的配置有问题&a…...
STM32-笔记37-吸烟室管控系统项目
一、项目需求 1. 使用 mq-2 获取环境烟雾值,并显示在 LCD1602 上; 2. 按键修改阈值,并显示在 LCD1602 上; 3. 烟雾值超过阈值时,蜂鸣器长响,风扇打开;烟雾值小于阈值时,蜂鸣器不响…...
2025-01-04 Unity插件 YodaSheet1 —— 插件介绍
文章目录 1 介绍2 工作原理2.1 ScriptableObject -> YadeSheetData2.2 YadeDatabase 存储多个 YadeSheetData 3 用途4 缺点5 推荐 1 介绍 Yade 提供类似于 Excel 或者 Google Sheets 的表格编辑器,可以轻松地在 Unity 编辑器中 编辑,搜索…...
电子电气架构 --- 安全相关内容汇总
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...
科研绘图系列:R语言单细胞数据常见的可视化图形
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理图1图2图3图4图5图6系统信息参考介绍 单细胞数据常见的可视化图形 因为本教程是单细胞数据,因此运行本画图脚本需要电脑的内存最少32Gb 加载…...
【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 2:基础知识
目录 1 预热1.1 记号1.2 分类器计算过载问题 2 多头编码(MHE)2.1 标签分解2.2 多头组合(Multi-Head Combination) 论文:Multi-Head Encoding for Extreme Label Classification 作者:Daojun Liang, Haixia …...
Flink使用
Window下启动支持 下载或复制老版本的放在bin目录下即可; flink.bat echo off setlocalSET bin%~dp0 SET FLINK_HOME%bin%.. SET FLINK_LIB_DIR%FLINK_HOME%\lib SET FLINK_PLUGINS_DIR%FLINK_HOME%\pluginsSET JVM_ARGS-Xmx512mSET FLINK_JM_CLASSPATH%FLINK_LI…...
一种可复用的AI提效方案:AI点灯
在当今飞速发展的时代,AI技术正不断渗透到我们生活的各个层面,深刻改变着传统的工作方式和生活模式。面对这一重大变革,我们不能被动观望或抗拒,而应积极拥抱AI,将其作为成长的助力。只有与AI协同发展,才能…...
Django 模型
Django 模型 Django 模型是 Django 框架的核心组件之一,它用于定义应用程序的数据结构。在 Django 中,模型是 Python 类,通常继承自 django.db.models.Model。每个模型类代表数据库中的一个表,模型类的属性对应表中的字段。 1. 创建模型 创建 Django 模型非常简单。首先…...
【MySQL 探索者日志 】第二弹 —— 数据库基础
MySQL系列学习笔记: MySQL探索者日志__Zwy的博客-CSDN博客 各位于晏,亦菲们,请点赞关注! 我的个人主页: _Zwy-CSDN博客 目录 1、MySQL服务器,数据库,表关系 2、MySQL登录连接服务器 3、MyS…...
【51单片机-零基础chapter1】
安装软件(配套的有,不多赘述) 1.管理员身份运行keil和破解软件kegen 将CID代码复制粘贴到 一定要管理员方式,不然会error 插入板子 我的电脑,管理 1.如果是拯救者,查看端口,如果没有则显示隐藏 2.苹果不知道,好像不可以 3.其他电脑在"其他设备找" (注:本人在校已…...
stm32的掉电检测机制——PVD
有时在一些应用中,我们需要检测系统是否掉电了,或者要在掉电的瞬间需要做一些处理。 STM32内部自带PVD功能,用于对MCU供电电压VDD进行监控。 STM32就有这样的掉电检测机制——PVD(Programmable Voltage Detecter),即可编程电压检…...
电脑steam api dll缺失了怎么办?
电脑故障解析与自救指南:Steam API DLL缺失问题的全面解析 在软件开发与电脑维护的广阔天地里,我们时常会遇到各种各样的系统报错与文件问题,其中“Steam API DLL缺失”便是让不少游戏爱好者和游戏开发者头疼的难题之一。作为一名深耕软件开…...
Kotlin 协程基础知识总结七 —— Flow 与 Jetpack Paging3
专题分为五大块: Paging3 的结构组成Flow 与 Paging3下拉刷新上拉刷新离奇 Bug上游数据缓存 Demo 会还原开发迭代的过程,不会直接一步到位。 1、Paging3 加载数据流程 (P105)Paging3 的简介详情可参考官方文档 Paging 库概览&…...
使用JMeter玩转tidb压测
作者: du拉松 原文来源: https://tidb.net/blog/3f1ada39 一、前言 tidb是mysql协议的,所以在使用过程中使用tidb的相关工具连接即可。因为jmeter是java开发的相关工具,直接使用mysql的jdbc驱动包即可。 二、linux下安装jmet…...
音视频入门基础:MPEG2-PS专题(3)——MPEG2-PS格式简介
一、引言 本文对MPEG2-PS格式进行简介。 进行简介之前,请各位先下载MPEG2-PS的官方文档。ITU-T和ISO/IEC都分别提供MPEG2-PS的官方文档。但是ITU提供的文档是免费的,ISO/IEC是付费的,所以我们主要阅读ITU提供的官方文档,比如较新…...
ETCD渗透利用指南
目录 未指定使用put操作报错 未指定操作版本使用get报错 首先etcd分为两个版本v2和v3,不同的API结果无论是访问URL还是使用etcdctl进行通信,都会导致问题,例如使用etcdctl和v3进行通信,如果没有实名ETCDCTL_API3指定API版本会直接…...
Python安装(新手详细版)
前言 第一次接触Python,可能是爬虫或者是信息AI开发的小朋友,都说Python 语言简单,那么多学一些总是有好处的,下面从一个完全不懂的Python 的小白来安装Python 等一系列工作的记录,并且遇到的问题也会写出,…...
SQL 中复杂 CASE WHEN 嵌套逻辑优化
目标:优化复杂的 CASE WHEN 逻辑,提升 SQL 语句的可读性与执行效率,减少多层嵌套带来的复杂性。 1. CASE WHEN 的常见问题 嵌套过深:多个条件判断嵌套,难以阅读和维护。重复逻辑:相似逻辑在多个分支中重复…...
【专题】2024年出口跨境电商促销趋势白皮书报告汇总PDF洞察(附原数据表)
原文链接:https://tecdat.cn/?p38722 在当今全球化加速演进、数字经济蓬勃发展的大背景下,跨境电商行业正以前所未有的态势重塑国际贸易格局,成为各方瞩目的焦点领域。 根据亚马逊发布的《2024年出口跨境电商促销趋势白皮书》,…...