带你写出符合 Promise/A+ 规范 Promise 的源码
Promise是前端面试中的高频问题,如果你能根据PromiseA+的规范,写出符合规范的源码,那么我想,对于面试中的Promise相关的问题,都能够给出比较完美的答案。
我的建议是,对照规范多写几次实现,也许第一遍的时候,是改了多次,才能通过测试,那么需要反复的写,我已经将Promise的源码实现写了不下七遍,不那么聪明的话,当然需要更加努力啦~
Promise的源码实现
/*** 1. new Promise时,需要传递一个 executor 执行器,执行器立刻执行* 2. executor 接受两个参数,分别是 resolve 和 reject* 3. promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled* 4. promise 的状态一旦确认,就不会再改变* 5. promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, * 和 promise 失败的回调 onRejected* 6. 如果调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值作为参数传递进去。* 如果promise已经失败,那么执行 onRejected, 并将 promise 失败的原因作为参数传递进去。* 如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(发布订阅)* 7. then 的参数 onFulfilled 和 onRejected 可以缺省* 8. promise 可以then多次,promise 的then 方法返回一个 promise* 9. 如果 then 返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功的回调(onFulfilled)* 10. 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调(onRejected)* 11.如果 then 返回的是一个promise,那么会等这个promise执行完,promise如果成功,* 就走下一个then的成功,如果失败,就走下一个then的失败*/const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise(executor) {let self = this;self.status = PENDING;self.onFulfilled = [];//成功的回调self.onRejected = []; //失败的回调//PromiseA+ 2.1function resolve(value) {if (self.status === PENDING) {self.status = FULFILLED;self.value = value;self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1}}function reject(reason) {if (self.status === PENDING) {self.status = REJECTED;self.reason = reason;self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2}}try {executor(resolve, reject);} catch (e) {reject(e);}
}Promise.prototype.then = function (onFulfilled, onRejected) {//PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };let self = this;//PromiseA+ 2.2.7let promise2 = new Promise((resolve, reject) => {if (self.status === FULFILLED) {//PromiseA+ 2.2.2//PromiseA+ 2.2.4 --- setTimeoutsetTimeout(() => {try {//PromiseA+ 2.2.7.1let x = onFulfilled(self.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {//PromiseA+ 2.2.7.2reject(e);}});} else if (self.status === REJECTED) {//PromiseA+ 2.2.3setTimeout(() => {try {let x = onRejected(self.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});} else if (self.status === PENDING) {self.onFulfilled.push(() => {setTimeout(() => {try {let x = onFulfilled(self.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});});self.onRejected.push(() => {setTimeout(() => {try {let x = onRejected(self.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}});});}});return promise2;
}function resolvePromise(promise2, x, resolve, reject) {let self = this;//PromiseA+ 2.3.1if (promise2 === x) {reject(new TypeError('Chaining cycle'));}if (x && typeof x === 'object' || typeof x === 'function') {let used; //PromiseA+2.3.3.3.3 只能调用一次try {let then = x.then;if (typeof then === 'function') {//PromiseA+2.3.3then.call(x, (y) => {//PromiseA+2.3.3.1if (used) return;used = true;resolvePromise(promise2, y, resolve, reject);}, (r) => {//PromiseA+2.3.3.2if (used) return;used = true;reject(r);});}else{//PromiseA+2.3.3.4if (used) return;used = true;resolve(x);}} catch (e) {//PromiseA+ 2.3.3.2if (used) return;used = true;reject(e);}} else {//PromiseA+ 2.3.3.4resolve(x);}
}module.exports = Promise;
有专门的测试脚本可以测试所编写的代码是否符合PromiseA+的规范。
首先,在promise实现的代码中,增加以下代码:
Promise.defer = Promise.deferred = function () {let dfd = {};dfd.promise = new Promise((resolve, reject) => {dfd.resolve = resolve;dfd.reject = reject;});return dfd;
}
安装测试脚本:
npm install -g promises-aplus-tests
如果当前的promise源码的文件名为promise.js
那么在对应的目录执行以下命令:
promises-aplus-tests promise.js
promises-aplus-tests中共有872条测试用例。以上代码,可以完美通过所有用例。
对上面的代码实现做一点简要说明(其它一些内容注释中已经写得很清楚):
- onFulfilled 和 onFulfilled的调用需要放在setTimeout,因为规范中表示: onFulfilled or onRejected must not be called until the execution context stack contains only platform code。使用setTimeout只是模拟异步,原生Promise并非是这样实现的。
- 在 resolvePromise 的函数中,为何需要usedd这个flag,同样是因为规范中明确表示: If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored. 因此我们需要这样的flag来确保只会执行一次。
- self.onFulfilled 和 self.onRejected 中存储了成功的回调和失败的回调,根据规范2.6显示,当promise从pending态改变的时候,需要按照顺序去指定then对应的回调。
PromiseA+的规范(翻译版)
PS: 下面是我翻译的规范,供参考
术语
- promise 是一个有then方法的对象或者是函数,行为遵循本规范
- thenable 是一个有then方法的对象或者是函数
- value 是promise状态成功时的值,包括 undefined/thenable或者是 promise
- exception 是一个使用throw抛出的异常值
- reason 是promise状态失败时的值
要求
2.1 Promise States
Promise 必须处于以下三个状态之一: pending, fulfilled 或者是 rejected
2.1.1 如果promise在pending状态
2.1.1.1 可以变成 fulfilled 或者是 rejected
2.1.2 如果promise在fulfilled状态
2.1.2.1 不会变成其它状态2.1.2.2 必须有一个value值
2.1.3 如果promise在rejected状态
2.1.3.1 不会变成其它状态2.1.3.2 必须有一个promise被reject的reason
概括即是:promise的状态只能从pending变成fulfilled,或者从pending变成rejected.promise成功,有成功的value.promise失败的话,有失败的原因
2.2 then方法
promise必须提供一个then方法,来访问最终的结果
promise的then方法接收两个参数
promise.then(onFulfilled, onRejected)
2.2.1 onFulfilled 和 onRejected 都是可选参数
2.2.1.1 onFulfilled 必须是函数类型2.2.1.2 onRejected 必须是函数类型
2.2.2 如果 onFulfilled 是函数:
2.2.2.1 必须在promise变成 fulfilled 时,调用 onFulfilled,参数是promise的value
2.2.2.2 在promise的状态不是 fulfilled 之前,不能调用
2.2.2.3 onFulfilled 只能被调用一次
2.2.3 如果 onRejected 是函数:
2.2.3.1 必须在promise变成 rejected 时,调用 onRejected,参数是promise的reason
2.2.3.2 在promise的状态不是 rejected 之前,不能调用
2.2.3.3 onRejected 只能被调用一次
2.2.4 onFulfilled 和 onRejected 应该是微任务
2.2.5 onFulfilled 和 onRejected 必须作为函数被调用
2.2.6 then方法可能被多次调用
2.2.6.1 如果promise变成了 fulfilled态,所有的onFulfilled回调都需要按照then的顺序执行
2.2.6.2 如果promise变成了 rejected态,所有的onRejected回调都需要按照then的顺序执行
2.2.7 then必须返回一个promise
promise2 = promise1.then(onFulfilled, onRejected);
2.2.7.1 onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
2.2.7.2 如果 onFulfilled 或者 onRejected 执行时抛出异常e,promise2需要被reject
2.2.7.3 如果 onFulfilled 不是一个函数,promise2 以promise1的值fulfilled
2.2.7.4 如果 onRejected 不是一个函数,promise2 以promise1的reason rejected
2.3 resolvePromise
resolvePromise(promise2, x, resolve, reject)
2.3.1 如果 promise2 和 x 相等,那么 reject promise with a TypeError
2.3.2 如果 x 是一个 promsie
2.3.2.1 如果x是pending态,那么promise必须要在pending,直到 x 变成 fulfilled or rejected.
2.3.2.2 如果 x 被 fulfilled, fulfill promise with the same value.
2.3.2.3 如果 x 被 rejected, reject promise with the same reason.
2.3.3 如果 x 是一个 object 或者 是一个 function
2.3.3.1 let then = x.then.
2.3.3.2 如果 x.then 这步出错,那么 reject promise with e as the reason..
2.3.3.3 如果 then 是一个函数,then.call(x, resolvePromiseFn, rejectPromise)2.3.3.3.1 resolvePromiseFn 的 入参是 y, 执行 resolvePromise(promise2, y, resolve, reject);2.3.3.3.2 rejectPromise 的 入参是 r, reject promise with r.2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都调用了,那么第一个调用优先,后面的调用忽略。2.3.3.3.4 如果调用then抛出异常e 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,那么忽略2.3.3.3.4.3 否则,reject promise with e as the reason
2.3.3.4 如果 then 不是一个function. fulfill promise with x.
2.3.4 如果 x 不是一个 object 或者 function,fulfill promise with x.
Promise的其他方法
虽然上述的promise源码已经符合PromiseA+的规范,但是原生的Promise还提供了一些其他方法,如:
- Promise.resolve()
- Promise.reject()
- Promise.prototype.catch()
- Promise.prototype.finally()
- Promise.all()
- Promise.race()
下面具体说一下每个方法的实现:
Promise.resolve
Promise.resolve(value) 返回一个以给定值解析后的Promise 对象.
- 如果 value 是个 thenable 对象,返回的promise会“跟随”这个thenable的对象,采用它的最终状态
- 如果传入的value本身就是promise对象,那么Promise.resolve将不做任何修改、原封不动地返回这个promise对象。
- 其他情况,直接返回以该值为成功状态的promise对象。
Promise.resolve = function (param) {if (param instanceof Promise) {return param;}return new Promise((resolve, reject) => {if (param && typeof param === 'object' && typeof param.then === 'function') {setTimeout(() => {param.then(resolve, reject);});} else {resolve(param);}});
}
thenable对象的执行加 setTimeout的原因是根据原生Promise对象执行的结果推断的,如下的测试代码,原生的执行结果为: 20 400 30;为了同样的执行顺序,增加了setTimeout延时。
测试代码:
let p = Promise.resolve(20);
p.then((data) => {console.log(data);
});let p2 = Promise.resolve({then: function(resolve, reject) {resolve(30);}
});p2.then((data)=> {console.log(data)
});let p3 = Promise.resolve(new Promise((resolve, reject) => {resolve(400)
}));
p3.then((data) => {console.log(data)
});
Promise.reject
Promise.reject方法和Promise.resolve不同,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。
Promise.reject = function (reason) {return new Promise((resolve, reject) => {reject(reason);});
}
Promise.prototype.catch
Promise.prototype.catch 用于指定出错时的回调,是特殊的then方法,catch之后,可以继续 .then
Promise.prototype.catch = function (onRejected) {return this.then(null, onRejected);
}
Promise.prototype.finally
不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.
Promise.prototype.finally = function (callback) {return this.then((value) => {return Promise.resolve(callback()).then(() => {return value;});}, (err) => {return Promise.resolve(callback()).then(() => {throw err;});});
}
Promise.all
Promise.all(promises) 返回一个promise对象
- 如果传入的参数是一个空的可迭代对象,那么此promise对象回调完成(resolve),只有此情况,是同步执行的,其它都是异步返回的。
- 如果传入的参数不包含任何 promise,则返回一个异步完成.
- promises 中所有的promise都promise都“完成”时或参数中不包含 promise 时回调完成。
- 如果参数中有一个promise失败,那么Promise.all返回的promise对象失败
- 在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组
Promise.all = function (promises) {promises = Array.from(promises);//将可迭代对象转换为数组return new Promise((resolve, reject) => {let index = 0;let result = [];if (promises.length === 0) {resolve(result);} else {function processValue(i, data) {result[i] = data;if (++index === promises.length) {resolve(result);}}for (let i = 0; i < promises.length; i++) {//promises[i] 可能是普通值Promise.resolve(promises[i]).then((data) => {processValue(i, data);}, (err) => {reject(err);return;});}}});
}
测试代码:
var promise1 = new Promise((resolve, reject) => {resolve(3);
})
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {setTimeout(resolve, 100, 'foo');
});Promise.all([promise1, promise2, promise3]).then(function(values) {console.log(values); //[3, 42, 'foo']
},(err)=>{console.log(err)
});var p = Promise.all([]); // will be immediately resolved
var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
console.log(p);
console.log(p2)
setTimeout(function(){console.log('the stack is now empty');console.log(p2);
});
Promise.race
Promise.race函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
如果传的参数数组是空,则返回的 promise 将永远等待。
如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。
Promise.race = function (promises) {promises = Array.from(promises);//将可迭代对象转换为数组return new Promise((resolve, reject) => {if (promises.length === 0) {return;} else {for (let i = 0; i < promises.length; i++) {Promise.resolve(promises[i]).then((data) => {resolve(data);return;}, (err) => {reject(err);return;});}}});
}
测试代码:
Promise.race([new Promise((resolve, reject) => { setTimeout(() => { resolve(100) }, 1000) }),undefined,new Promise((resolve, reject) => { setTimeout(() => { reject(100) }, 100) })
]).then((data) => {console.log('success ', data);
}, (err) => {console.log('err ',err);
});Promise.race([new Promise((resolve, reject) => { setTimeout(() => { resolve(100) }, 1000) }),new Promise((resolve, reject) => { setTimeout(() => { resolve(200) }, 200) }),new Promise((resolve, reject) => { setTimeout(() => { reject(100) }, 100) })
]).then((data) => {console.log(data);
}, (err) => {console.log(err);
});
相关文章:
带你写出符合 Promise/A+ 规范 Promise 的源码
Promise是前端面试中的高频问题,如果你能根据PromiseA的规范,写出符合规范的源码,那么我想,对于面试中的Promise相关的问题,都能够给出比较完美的答案。 我的建议是,对照规范多写几次实现,也许…...
回流与重绘
触发回流与重绘条件👉回流当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为 回流。引起回流原因1.页面的首次渲染2.浏览器的窗口大小发生变化3.元素的内容发生变化4.元素的尺寸或者位置发生变化…...
openpyxl表格的简单实用
示例:创建简单的电子表格和条形图 在这个例子中,我们将从头开始创建一个工作表并添加一些数据,然后绘制它。我们还将探索一些有限的单元格样式和格式。 我们将在工作表上输入的数据如下: 首先,让我们加载 openpyxl 并创建一个新工作簿。并获取活动表。我们还将输入我们…...
【寒假day4】leetcode刷题
🌈一、选择题❤1.下列哪一个是析构函数的特征( )。A: 析构函数定义只能在类体内 B: 一个类中只能定义一个析构函数 C: 析构函数名与类名相同 D: 析构函数可以有一个或多个参数答案:B答案解析:析构函数是构造函…...
【竞赛题】6355. 统计公平数对的数目
题目: 给你一个下标从 0 开始、长度为 n 的整数数组 nums ,和两个整数 lower 和 upper ,返回 公平数对的数目 。 如果 (i, j) 数对满足以下情况,则认为它是一个 公平数对 : 0 < i < j < n,且 l…...
Redis集群搭建(主从、哨兵、分片)
1.单机安装Redis 首先需要安装Redis所需要的依赖: yum install -y gcc tcl然后将课前资料提供的Redis安装包上传到虚拟机的任意目录: 例如,我放到了/tmp目录: 解压缩: tar -xzf redis-6.2.4.tar.gz解压后࿱…...
Dart语法基础补充
Asynchrony support Dart 库中充满了返回 Future 或 Stream 对象的函数。 这些函数是异步的:它们在设置一个可能耗时的操作(例如 I/O)后返回,而不等待该操作完成。 async 和 await 关键字支持异步编程,让编写看起来类…...
Nginx - 深入理解nginx的处理请求、进程关系和配置文件重载
概述 Nginx的系统学习整理的第三篇博客,主要介绍nginx的应用场景和架构基础,以便更好的理解,再生产环境中进行性能调优。 Nginx的三个主要应用场景 1.静态资源服务,通过本地文件系统提供服务 2.反向代理服务,强大的性…...
华为OD机试 - 服务依赖(Python)| 真题含思路
服务依赖 题目 在某系统中有众多服务,每个服务用字符串(只包含字母和数字,长度<=10)唯一标识,服务间可能有依赖关系,如A依赖B,则当 B 故障时导致 A 也故障。 传递具有依赖性,如 A依赖 B,B 依赖 C,当 C 故障时导致 B 故障,也导致 A 故障。给出所有依赖关系以及当…...
html的表单标签(form)
目录标题1、表单标签主要有三大类:2、表单标签中常见的属性3、例子代码及结果4、注意:5、表单中特殊的属性表单标签可以用来数据交互,而前面学的六个标签只能发送不能接收。 表单标签的作用就是数据交互1、表单标签主要有三大类: …...
手把手教你部署ruoyi前后端分离版本
下载源码(当前版本3.8.5)RuoYi-Vue: 🎉 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本 (gitee.com)创建数据库(一定要是这三个&…...
JUC并发编程 Ⅱ -- 共享模型之管程(上)
文章目录共享带来的问题临界区 Critical Section竞态条件 Race Conditionsynchronized 解决方案synchronized语法解决方案思考面向对象改进方法上的 synchronized线程八锁变量的线程安全分析成员变量和静态变量是否线程安全?局部变量是否线程安全?局部变…...
File类
🏡个人主页 : 守夜人st 🚀系列专栏:Java …持续更新中敬请关注… 🙉博主简介:软件工程专业,在校学生,写博客是为了总结回顾一些所学知识点 ✈️推荐一款模拟面试,刷题神器…...
ModSecurity规则功能说明
ModSecurity规则功能说明 owasp规则: 第一部分:基础规则集 modsecurity_crs_20_protocol_violations.conf HTTP协议规范相关规则modsecurity_crs_21_protocol_anomalies.conf HTTP协议规范相关规则modsecurity_crs_23_request_limits.conf HTTP协议大小长度限制相…...
医学生考研考博太卷,一篇文章轻松助力上岸(一)
考研考博太卷了,卷不过,想没想过本科发一篇文章呢? 330分考研人淘汰390分考研人这个故事,大家应该都知道吧。 本专栏带你六个月内,搞定一篇文章,本科生发文章也很容易。 在卷考研的同时,再卷…...
操作系统(一): 进程和线程,进程的多种状态以及进程的调度算法
文章目录前言一、进程和线程1. 进程2. 线程二、进程和线程的区别(面试常问)三、进程调度算法3.1. 批处理系统3.2. 交互式系统3.2.1 时间片轮转3.2.2 优先级调度3.2.3 多级别反馈队列3.3. 实时系统四、进程的状态五、进程同步5.1 什么是进程同步5.2 进程同步应该遵循的几点原则前…...
【随笔】我迟到的2022年度总结:突破零粉丝,1个月涨粉1000+,2023年目标3万+
前言 我是21年12月注册的csdn, 作为用户平时看看文章,从未参与过写文章这件事。 但这一年的时间我见证了很多新号的崛起,有的号我平时关注比较多,看着他们从零粉丝突破了三万甚至五万的粉丝量。 在csdn上遇到了我的贵人&#x…...
SpringCloud-Netflix学习笔记13——Zuul路由网关
什么是Zuul? Zuul包含了对请求的路由和过滤两个最主要的功能。 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能…...
Hive 之 DDL操作
DDL 操作是用于操作对象和对象的属性,这种对象包括数据库本身,以及数据库对象,像:表、视图等等 1. 数据库 1.1 创建数据库 数据库在 HDFS 上的默认存储路径是 /user/hive/warehouse/*.db CREATE (DATABASE|SCHEMA) [IF NOT EX…...
2. SpringMVC 请求与响应
文章目录1. 请求映射路径2. 请求参数2.1 get 请求发送普通参数2.2 post 请求发送普通参数2.3 五种类型的参数传递2.4.1 普通参数2.4.2 POJO 数据类型2.4.3 嵌套 POJO 类型参数2.4.4 数组类型参数2.4.5 集合类型参数3. json 数据传输参数(重点)3.1 传输 j…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...
