重试API let timer; let repeatTimes = 0; async function P2UploadFile(fileName) { return new Promise((res) => setTimeout(() => res(fileName), 2000)); } async function getP6upload2(params) { repeatTimes++; //暂且认为这是正确的道响应结果 要关闭继续调取定时器 //我们给一个状态 这是一个通过的条件 const condition = Math.random() > 0.6; console.log('condition', condition); if (condition) { resetRequest(); return 'pass'; } else { console.log('repeatTimes', repeatTimes); return 'forbidden'; } } function resetRequest() { if (timer) { clearTimeout(timer); timer = null; } repeatTimes = 0; } function repeatQuest(fileName) { if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(async () => { try { const result = await getP6upload2(fileName); if (result !== 'pass' && repeatTimes < 6) { repeatQuest(fileName); } else { console.log('结束运行'); resetRequest(); } } catch (e) { console.log('e', e); if (repeatTimes < 6) { repeatQuest(fileName); } else { resetRequest(); } } }, 2000); } // P2UploadFile('a.txt').then((fileName) => { // console.log(fileName); // repeatQuest(fileName); // }); /** * 封装一个通用的接口重试函数 * @param {Function} fn - 返回 Promise 的函数(例如 fetch 调用) * @param {number} retries - 最大重试次数 * @param {number} delay - 每次重试间隔时间(毫秒) * @param {Function} shouldRetry - 可选:是否应该重试(默认只在抛出异常时重试) * @returns {Promise<any>} */ async function retryRequest(fn, retries = 3, delay = 1000, shouldRetry = null) { for (let attempt = 0; attempt <= retries; attempt++) { try { const result = await fn(); if (shouldRetry && !shouldRetry(result)) { // 如果有 shouldRetry 并返回 false,认为不满足重试条件 return result; } return result; } catch (err) { console.log('err', err); if (attempt === retries) { throw err; } await new Promise((resolve) => setTimeout(resolve, delay)); } } } function testAPI() { return new Promise((res, rej) => { const random = Math.random(); console.log('random', random); if (random > 0.8) { res('success'); } else { rej('error'); } }); } retryRequest(testAPI, 6, 2000, (res) => { console.log('res', res); return res !== 'success'; });
Webpack
Webpack 详解 1. Webpack 是什么 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将这些模块打包成一个或多个 bundle。 2. Webpack 的安装 npm install webpack webpack-cli --save-dev 3. Webpack 的配置 3.1 entry 入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。 // webpack.config.js module.exports = { entry: "./src/index.js", }; 3.2 output output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist/main.js。 // webpack.config.js module.exports = { entry: "./src/index.js", output: { filename: "bundle.js", path: __dirname + "/dist", }, }; 3.3 loader loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块。 ...
任务中断和恢复
任务中断和恢复 实现 /** * 依次顺序执行一系列任务 * 所有任务完成后可以得到每个任务的执行结果 * 需要返回两个方法,start用于启动项目,pause用于终止任务 * 每个任务具有原子性,即不可中断,只能在两个任务之间可以中断 * @param {...Function} tasks 任务列表 每个任务无参 且异步 * */ function processTasks(tasks) { let isRunning = false; let result = []; let i = 0; return { start() { return new Promise(async (resolve) => { if (isRunning) { return; } isRunning = true; // 执行任务 while (i < tasks.length) { const task = tasks.shift(); const res = await task(); result.push(res); i++; if (!isRunning) { return; } } // 任务完成 isRunning = false; resolve(result); }); }, pause() { isRunning = false; }, }; } 使用 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <script src="../js/任务队列的中断和恢复.js"></script> </head> <body> <button id="start">启动</button> <br /> <button id="pause">暂停</button> <script> window.onload = function () { const tasks = []; for (let i = 0; i < 10; i++) { tasks.push(function () { console.log("任务" + (i + 1) + "执行中..."); return new Promise((resolve, reject) => { setTimeout(() => { resolve(i); console.log("任务" + (i + 1) + "执行完毕"); }, 2000); }); }); } const start = document.getElementById("start"); const pause = document.getElementById("pause"); const processor = processTasks(tasks); start.onclick = async function () { console.log("开始执行任务"); const res = await processor.start(); console.log("所有任务执行完毕,结果为:", res); }; pause.onclick = function () { console.log("暂停执行任务"); processor.pause(); }; }; </script> </body> </html> 测试结果 ...
并发任务
并发请求任务 实现 /** * * @param {*} urls 请求的集合 * @param {*} maxNum 最大请求数量 * @returns */ function concurrentRequest(urls, maxNum) { if (urls.length === 0) { return Promise.resolve([]); } return new Promise((resolve, reject) => { const result = []; // 存放请求结果 let nextIndex = 0; // 下一个请求的索引 let finishCount = 0; // 完成的请求数量 async function _request() { if (nextIndex > urls.length) { return; } const currentRequestIndex = nextIndex; // 当前请求的索引 const url = urls[nextIndex++]; // 获取下一个请求的url const resp = await fetch(url).then((res) => res.json()); // 发送请求 result[currentRequestIndex] = resp; // 存放请求结果 finishCount++; // 完成的请求数量+1 // 递归调用,直到所有请求完成 if (finishCount === urls.length) { resolve(result); // 所有请求完成,返回结果 return; } _request(); // 补位递归调用 // console.log("result", result); } for (let i = 0; i < Math.min(maxNum, urls.length); i++) { _request(); // 开始其他请求 } }); } //测试 const urls = Array.from({ length: 20 }).map( (_, i) => `https://jsonplaceholder.typicode.com/todos/${i + 1}` ); console.log("urls", urls); concurrentRequest(urls, 5).then((res) => { console.log(res); }); 测试结果 ...
Java Pom.xml
pom.xml 常用标签大全 标签 作用 示例 <project> 必须的根标签,所有内容都包裹在里面。 <project xmlns=...>...</project> <modelVersion> 定义 POM 模型的版本(固定写法)。通常是 4.0.0。 <modelVersion>4.0.0</modelVersion> <groupId> 项目组织 ID,通常是公司或组织的域名倒写。 <groupId>com.example</groupId> <artifactId> 项目的名字,通常是模块或应用名称。 <artifactId>admin-backend</artifactId> <version> 项目的版本号。 <version>1.0.0</version> <packaging> 打包方式,默认是 jar,也可以是 war(Web 项目)。 <packaging>jar</packaging> <name> 项目的名称(可选,主要用于描述)。 <name>Admin Backend System</name> <description> 项目的简短描述(可选)。 <description>A Spring Boot Admin system</description> 依赖管理相关标签 标签 作用 示例 <dependencies> 依赖列表,包含所有 <dependency>。 <dependencies>...</dependencies> <dependency> 单个依赖项。 <dependency>...</dependency> <groupId> 依赖库的组织 ID。 <groupId>org.springframework.boot</groupId> <artifactId> 依赖库的名称。 <artifactId>spring-boot-starter-web</artifactId> <version> 依赖库的版本号。 <version>3.1.2</version> <scope> 依赖范围(如 compile、test、provided)。 <scope>test</scope> 常见 scope: compile(默认):编译、运行、打包都需要。 test:仅在测试阶段需要。 provided:编译需要,运行环境已提供,比如 Servlet API。 构建配置相关标签 标签 作用 示例 <build> 构建配置(比如插件、输出目录)。 <build>...</build> <plugins> 插件列表,包含多个 <plugin>。 <plugins>...</plugins> <plugin> 单个插件。比如 Maven 编译器插件、打包插件等。 <plugin>...</plugin> 例子:指定 Java 版本 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>17</source> <target>17</target> </configuration> </plugin> </plugins> </build> 其他常见的标签 标签 作用 示例 <properties> 定义一些可以重复使用的属性,比如 Java 版本号、编码格式。 <properties><java.version>17</java.version></properties> <repositories> 指定 Maven 仓库地址(如果用私服)。 <repositories>…</repositories> <profiles> 多环境配置,比如开发版、生产版不同配置。 <profiles>…</profiles> 常见配置举例 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 项目信息 --> <groupId>com.example</groupId> <artifactId>springboot-demo</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>springboot-demo</name> <description>Spring Boot 后端项目模板</description> <!-- 父工程,管理 Spring Boot 依赖版本 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.2</version> <!-- 根据你的 Spring Boot 版本选择 --> <relativePath/> </parent> <!-- 统一配置 --> <properties> <java.version>17</java.version> <!-- Java 17 --> <maven.compiler.source>${java.version}</maven.compiler.source> <maven.compiler.target>${java.version}</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <!-- 项目依赖 --> <dependencies> <!-- Spring Boot 核心 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Boot Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- 测试 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 构建配置 --> <build> <plugins> <!-- 编译 Java 版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <!-- Spring Boot Maven 插件:用于打包 jar --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
代理实现单例模式
前言 单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。在 JavaScript 中,单例模式可以通过代理实现,代理模式是一种设计模式,它允许你将一个对象的操作委托给另一个对象。 代理实现单例模式 // 代理实现单例模式 function ProxySingletonFactory(fn) { let instance = null; return function (...args) { if (!instance) { instance = fn.apply(this, args); } return instance; }; } // 测试 const createSingleDog = ProxySingletonFactory(function () { console.log("创建狗"); return "dog"; }); console.log(createSingleDog()); console.log(createSingleDog()); console.log(createSingleDog()); 但是如果是异步调用呢; 我们如何对类进行封装实现单例全局唯一 class A { constructor() { console.log("初始化A"); } } function singlton(classname) { let ins; const proxy = new Proxy(classname, { construct(target, args) { if (ins) { return ins; } ins = Reflect.construct(target, args); return ins; }, }); proxy.prototype.constructor = proxy; return proxy; } const AProxy = singlton(A); export default return new AProxy(); 总结 通过代理实现单例模式,可以确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这种方式可以避免全局变量污染,并且可以在需要的时候才创建实例,从而提高性能。 ...