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

带你写出符合 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条测试用例。以上代码,可以完美通过所有用例。

对上面的代码实现做一点简要说明(其它一些内容注释中已经写得很清楚):

  1. onFulfilled 和 onFulfilled的调用需要放在setTimeout,因为规范中表示: onFulfilled or onRejected must not be called until the execution context stack contains only platform code。使用setTimeout只是模拟异步,原生Promise并非是这样实现的。
  2. 在 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来确保只会执行一次。
  3. self.onFulfilled 和 self.onRejected 中存储了成功的回调和失败的回调,根据规范2.6显示,当promise从pending态改变的时候,需要按照顺序去指定then对应的回调。

PromiseA+的规范(翻译版)

PS: 下面是我翻译的规范,供参考

术语

  1. promise 是一个有then方法的对象或者是函数,行为遵循本规范
  2. thenable 是一个有then方法的对象或者是函数
  3. value 是promise状态成功时的值,包括 undefined/thenable或者是 promise
  4. exception 是一个使用throw抛出的异常值
  5. 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还提供了一些其他方法,如:

  1. Promise.resolve()
  2. Promise.reject()
  3. Promise.prototype.catch()
  4. Promise.prototype.finally()
  5. Promise.all()
  6. Promise.race()

下面具体说一下每个方法的实现:

Promise.resolve

Promise.resolve(value) 返回一个以给定值解析后的Promise 对象.

  1. 如果 value 是个 thenable 对象,返回的promise会“跟随”这个thenable的对象,采用它的最终状态
  2. 如果传入的value本身就是promise对象,那么Promise.resolve将不做任何修改、原封不动地返回这个promise对象。
  3. 其他情况,直接返回以该值为成功状态的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对象

  1. 如果传入的参数是一个空的可迭代对象,那么此promise对象回调完成(resolve),只有此情况,是同步执行的,其它都是异步返回的。
  2. 如果传入的参数不包含任何 promise,则返回一个异步完成.
  3. promises 中所有的promise都promise都“完成”时或参数中不包含 promise 时回调完成。
  4. 如果参数中有一个promise失败,那么Promise.all返回的promise对象失败
  5. 在任何情况下,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是前端面试中的高频问题&#xff0c;如果你能根据PromiseA的规范&#xff0c;写出符合规范的源码&#xff0c;那么我想&#xff0c;对于面试中的Promise相关的问题&#xff0c;都能够给出比较完美的答案。 我的建议是&#xff0c;对照规范多写几次实现&#xff0c;也许…...

回流与重绘

触发回流与重绘条件&#x1f449;回流当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时&#xff0c;浏览器会重新渲染部分或者全部文档的过程就称为 回流。引起回流原因1.页面的首次渲染2.浏览器的窗口大小发生变化3.元素的内容发生变化4.元素的尺寸或者位置发生变化…...

openpyxl表格的简单实用

示例:创建简单的电子表格和条形图 在这个例子中,我们将从头开始创建一个工作表并添加一些数据,然后绘制它。我们还将探索一些有限的单元格样式和格式。 我们将在工作表上输入的数据如下: 首先,让我们加载 openpyxl 并创建一个新工作簿。并获取活动表。我们还将输入我们…...

【寒假day4】leetcode刷题

&#x1f308;一、选择题❤1.下列哪一个是析构函数的特征&#xff08; &#xff09;。A: 析构函数定义只能在类体内 B: 一个类中只能定义一个析构函数 C: 析构函数名与类名相同 D: 析构函数可以有一个或多个参数答案&#xff1a;B答案解析&#xff1a;析构函数是构造函…...

【竞赛题】6355. 统计公平数对的数目

题目&#xff1a; 给你一个下标从 0 开始、长度为 n 的整数数组 nums &#xff0c;和两个整数 lower 和 upper &#xff0c;返回 公平数对的数目 。 如果 (i, j) 数对满足以下情况&#xff0c;则认为它是一个 公平数对 &#xff1a; 0 < i < j < n&#xff0c;且 l…...

Redis集群搭建(主从、哨兵、分片)

1.单机安装Redis 首先需要安装Redis所需要的依赖&#xff1a; yum install -y gcc tcl然后将课前资料提供的Redis安装包上传到虚拟机的任意目录&#xff1a; 例如&#xff0c;我放到了/tmp目录&#xff1a; 解压缩&#xff1a; tar -xzf redis-6.2.4.tar.gz解压后&#xff1…...

Dart语法基础补充

Asynchrony support Dart 库中充满了返回 Future 或 Stream 对象的函数。 这些函数是异步的&#xff1a;它们在设置一个可能耗时的操作&#xff08;例如 I/O&#xff09;后返回&#xff0c;而不等待该操作完成。 async 和 await 关键字支持异步编程&#xff0c;让编写看起来类…...

Nginx - 深入理解nginx的处理请求、进程关系和配置文件重载

概述 Nginx的系统学习整理的第三篇博客&#xff0c;主要介绍nginx的应用场景和架构基础&#xff0c;以便更好的理解&#xff0c;再生产环境中进行性能调优。 Nginx的三个主要应用场景 1.静态资源服务&#xff0c;通过本地文件系统提供服务 2.反向代理服务&#xff0c;强大的性…...

华为OD机试 - 服务依赖(Python)| 真题含思路

服务依赖 题目 在某系统中有众多服务,每个服务用字符串(只包含字母和数字,长度<=10)唯一标识,服务间可能有依赖关系,如A依赖B,则当 B 故障时导致 A 也故障。 传递具有依赖性,如 A依赖 B,B 依赖 C,当 C 故障时导致 B 故障,也导致 A 故障。给出所有依赖关系以及当…...

html的表单标签(form)

目录标题1、表单标签主要有三大类&#xff1a;2、表单标签中常见的属性3、例子代码及结果4、注意&#xff1a;5、表单中特殊的属性表单标签可以用来数据交互&#xff0c;而前面学的六个标签只能发送不能接收。 表单标签的作用就是数据交互1、表单标签主要有三大类&#xff1a; …...

手把手教你部署ruoyi前后端分离版本

下载源码&#xff08;当前版本3.8.5&#xff09;RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue & Element 的前后端分离权限管理系统&#xff0c;同时提供了 Vue3 的版本 (gitee.com)创建数据库(一定要是这三个&…...

JUC并发编程 Ⅱ -- 共享模型之管程(上)

文章目录共享带来的问题临界区 Critical Section竞态条件 Race Conditionsynchronized 解决方案synchronized语法解决方案思考面向对象改进方法上的 synchronized线程八锁变量的线程安全分析成员变量和静态变量是否线程安全&#xff1f;局部变量是否线程安全&#xff1f;局部变…...

File类

&#x1f3e1;个人主页 &#xff1a; 守夜人st &#x1f680;系列专栏&#xff1a;Java …持续更新中敬请关注… &#x1f649;博主简介&#xff1a;软件工程专业&#xff0c;在校学生&#xff0c;写博客是为了总结回顾一些所学知识点 ✈️推荐一款模拟面试&#xff0c;刷题神器…...

ModSecurity规则功能说明

ModSecurity规则功能说明 owasp规则: 第一部分&#xff1a;基础规则集 modsecurity_crs_20_protocol_violations.conf HTTP协议规范相关规则modsecurity_crs_21_protocol_anomalies.conf HTTP协议规范相关规则modsecurity_crs_23_request_limits.conf HTTP协议大小长度限制相…...

医学生考研考博太卷,一篇文章轻松助力上岸(一)

考研考博太卷了&#xff0c;卷不过&#xff0c;想没想过本科发一篇文章呢&#xff1f; 330分考研人淘汰390分考研人这个故事&#xff0c;大家应该都知道吧。 本专栏带你六个月内&#xff0c;搞定一篇文章&#xff0c;本科生发文章也很容易。 在卷考研的同时&#xff0c;再卷…...

操作系统(一): 进程和线程,进程的多种状态以及进程的调度算法

文章目录前言一、进程和线程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&#xff0c; 作为用户平时看看文章&#xff0c;从未参与过写文章这件事。 但这一年的时间我见证了很多新号的崛起&#xff0c;有的号我平时关注比较多&#xff0c;看着他们从零粉丝突破了三万甚至五万的粉丝量。 在csdn上遇到了我的贵人&#x…...

SpringCloud-Netflix学习笔记13——Zuul路由网关

什么是Zuul? Zuul包含了对请求的路由和过滤两个最主要的功能。 其中路由功能负责将外部请求转发到具体的微服务实例上&#xff0c;是实现外部访问统一入口的基础&#xff0c;而过滤器功能则负责对请求的处理过程进行干预&#xff0c;是实现请求校验&#xff0c;服务聚合等功能…...

Hive 之 DDL操作

DDL 操作是用于操作对象和对象的属性&#xff0c;这种对象包括数据库本身&#xff0c;以及数据库对象&#xff0c;像&#xff1a;表、视图等等 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 数据传输参数&#xff08;重点&#xff09;3.1 传输 j…...

leaflet 读取上传的geojson文件,转换为wkt文件(057)

第057个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中上传geojson文件,解析geojson文件并转换为WKT,并在地图上显示图片。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共128行)安装 @terraf…...

面试题-前端开发Vue篇(答案超详细)

文章目录 如何实现跨域?JSONP原理和缺点谈谈你对DOM的理解及常用的DOM API说说你对 Vue 的理解说说 Vue 的优缺点什么是虚拟 DOM请描述下 vue 的生命周期是什么vue 如何监听键盘事件?watch 怎么深度监听对象变化删除数组用 delete 和 Vue.delete 有什么区别watch 和计算属性有…...

PTA甲级-1010 Radix c++

文章目录Input Specification:Output Specification:Sample Input 1:Sample Output 1:Sample Input 2:Sample Output 2:一、题干大意![在这里插入图片描述](https://img-blog.csdnimg.cn/68d84d3ea86e4aaab002152ae8472e05.png#pic_center)二、题解要点三、具体实现总结Given a…...

【项目重构】第1次思考

回顾与反思 2022年~至今&#xff08;2023年2月&#xff09;&#xff0c;一共重构了2个项目。 第1个项目在重构的时候&#xff0c;总是想着把别人的代码copy过来&#xff0c;改一改&#xff0c;这就算重构好了。这样做效率太低&#xff0c;原因是前人写的代码不一定有很多注释…...

Java:SpringMVC的使用(2)

目录第十二章 REST风格CRUD练习12.1 搭建环境12.2 实现功能思路第十三章 SpringMVC消息转换器13.1 消息转换器概述13.2 使用消息转换器处理请求报文(1) 使用RequestBody获取请求体(2) 使用HttpEntity\<T>获取请求体及请求头13.3 使用消息转换器处理响应报文(1) 使用Respo…...

Elasticsearch7.8.0版本进阶——分布式集群(应对故障)

目录一、Elasticsearch集群的安装1.1、Elasticsearch集群的安装&#xff08;win10环境&#xff09;1.2、Elasticsearch集群的安装&#xff08;linux环境&#xff09;二、应对故障&#xff08;win10环境集群演示&#xff09;2.1、启动集群&#xff08;三个节点&#xff09;2.2、…...

【LeetCode】每日一题(2)

目录 题目&#xff1a;1138. 字母板上的路径 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;1138. 字母板上的路径 - 力扣&am…...

软件设计师教程(六)计算机系统知识-操作系统知识

软件设计师教程 软件设计师教程&#xff08;一&#xff09;计算机系统知识-计算机系统基础知识 软件设计师教程&#xff08;二&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;三&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;…...

Zookeeper下载安装与集群搭建

Zookeeper下载安装与集群搭建1.下载安装1.1 下载安装1.2 配置启动2.集群搭建2.1 搭建要求2.2 准备工作2.3 配置集群2.4 启动集群2.5 模拟集群异常1.下载安装 1.1 下载安装 1、环境准备 ZooKeeper服务器是用Java创建的&#xff0c;它运行在JVM之上。需要安装JDK 7或更高版本。…...

Filter防火墙(8)

实验目的 1、了解个人防火墙的基本工作原理&#xff1b; 2、掌握Filter防火墙的配置。 预备知识防火墙 防火墙&#xff08;Firewall&#xff09;是一项协助确保信息安全的设备&#xff0c;会依照特定的规则&#xff0c;允许或是限制传输的数据通过。防火墙可以是一台专属的硬…...

学校网站免费建设/经典广告

在一些批处理或者系统技巧操作教程文章中&#xff0c;我们常常会看到一些形如 %windir% 或者 %systemdrive% 的变量。这些变量都代表着什么含义呢&#xff1f;下面小技巧之家为大家整理了在Windows XP下系统变量方式表达相对应的路径&#xff0c;大家可以看得更加清楚明白了&am…...

网站建设算入会计分录/seo 网站推广

《Docker技术入门与实践》 机械工业出版社 第十八章 Docker核心技术 Docker 归根到底是一种容器虚拟化技术。 本章介绍Docker的核心实现技术&#xff0c;包括架构、命名空间、控制组、联合文件系统、虚拟网络技术等话题。 早期版本Docker底层是基于成熟的Linux Container&a…...

页面设计网站素材/网站关键词搜索排名

这里介绍的是mt2523平台FAQ解决方案资料&#xff0c;需要mt2523相关技术资料或方案开发&#xff0c;可到一牛网论坛 mt2523 [GPS] 如何在MT2523上测试cold/warm/hot start TTFF&#xff1f; 1. 编译GNSS_get_location project&#xff0c;并且烧录image到设备 2. 将设备UART…...

微网站什么意思/网站关键词排名外包

Vector 类实现了一个动态数组。和 ArrayList 很相似&#xff0c;但是两者是不同的&#xff1a; Vector 是同步访问的。 Vector 包含了许多传统的方法&#xff0c;这些方法不属于集合框架。 Vector 主要用在事先不知道数组的大小&#xff0c;或者只是需要一个可以改变大小的数组…...

创建wordpress插件/自己建网站怎么弄

控制系统的方块图方块图的组成方块信号线分支点相加点方块图的化简方块图的等效变换比较点的等效变换引出点的等效变换系统的方块图&#xff0c;是描述系统中每个元件之间的功能和信号传递关系的数学模型&#xff0c;它表示系统各变量之间的因果关系以及对各变量所进行的运算&a…...

廊坊智能模板建站/海南网站制作

D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决参考文章&#xff1a; &#xff08;1&#xff09;D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决 &#xff08;2&#xff09;https://www.cnblogs.com/lmou/p/10896801.html &#…...