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

手写promise A+、catch、finally、all、allsettled、any、race

目录

手写promise

同步版

1.Promise的构造方法接收一个executor(),在new Promise()时就立刻执行executor回调

2.executor()内部的异步任务被放入宏/微任务队列,等待执行

3.状态与结果的管理

状态只能变更一次

4.then()调用成功/失败回调

catch是调用失败回调的简写

异步版

1.缓存成功与失败回调

2.then 增加 Pending处理

3.resolve 与 reject 中调用回调函数

多次调用同一个promise的then

1.缓存成功与失败回调 队列

2.pengding时,then()收集依赖,将成功/失败回调放入成功/失败队列

3.触发resolve/reject,从成功/失败队列中取出回调依次执行

then链式调用:返回一个 Promise 对象

then返回自己时,抛错循环调用

等返回的promise初始化好:queueMicrotask微任务

捕获错误

executor错误

then错误

then([onFulfilled, onRejected])参数可选

then 穿透:忽略非函数参数,非函数会同步执行

静态调用resolve、reject

完整版

Promise A+ 规范版的resolvePromise

catch

finally

并发请求

模板

all

allSettled

any

race


手写promise

同步版

1.将promise的resolve和reject函数传给实例用

 constructor(executor){// executor 是一个执行器,进入会立即执行// 并传入resolve和reject方法executor(this.resolve, this.reject) }

2.实例给resolve和reject函数传值

resolve('success')
reject('err')
// 新建 test.js// 引入我们的 MyPromise.js
const MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {resolve('success')reject('err')
})promise.then(value => {console.log('resolve', value)
}, reason => {console.log('reject', reason)
})// 执行结果:resolve success

1.Promise的构造方法接收一个executor(),在new Promise()时就立刻执行executor回调

class Promise{// 构造方法接收一个回调constructor(executor){executor();}

2.executor()内部的异步任务被放入宏/微任务队列,等待执行

  // resolve和reject为什么要用箭头函数?
  // 如果直接调用的话,普通函数this指向的是window或者undefined
  // 用箭头函数就可以让this指向当前实例对象

class MyPromise {constructor(executor){// executor 是一个执行器,进入会立即执行// 并传入resolve和reject方法executor(this.resolve, this.reject) }// 更改成功后的状态resolve = () => {}// 更改失败后的状态reject = () => {}
}

3.状态与结果的管理

状态只能变更一次
// 先定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';// 新建 MyPromise 类
class MyPromise {constructor(executor){...}// 储存状态的变量,初始值是 pendingstatus = PENDING;// 成功之后的值value = null;// 失败之后的原因reason = null;// 更改成功后的状态resolve = (value) => {// 只有状态是等待,才执行状态修改if (this.status === PENDING) {// 状态修改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;}}// 更改失败后的状态reject = (reason) => {// 只有状态是等待,才执行状态修改if (this.status === PENDING) {// 状态成功为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;}}
}

4.then()调用成功/失败回调

catch调用失败回调的简写
// MyPromise.jsthen(onFulfilled, onRejected) {// 判断状态if (this.status === FULFILLED) {// 调用成功回调,并且把值返回onFulfilled(this.value);} else if (this.status === REJECTED) {// 调用失败回调,并且把原因返回onRejected(this.reason);}
}

异步版

// test.jsconst MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {setTimeout(() => {resolve('success')}, 2000); 
})promise.then(value => {console.log('resolve', value)
}, reason => {console.log('reject', reason)
})// 同步版没有打印信息(执行到then时,状态还是pending)
// 异步版等待 2s 输出 resolve success

1.缓存成功与失败回调

// MyPromise 类中新增
// 存储成功回调函数
onFulfilledCallback = null;
// 存储失败回调函数
onRejectedCallback = null;

2.then 增加 Pending处理

// MyPromise.jsthen(onFulfilled, onRejected) {...if (this.status === PENDING) {// ==== 新增 ====// 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来// 等到执行成功失败函数的时候再传递this.onFulfilledCallback = onFulfilled;this.onRejectedCallback = onRejected;}
}

3.resolve 与 reject 中调用回调函数

// MyPromise.js// 更改成功后的状态
resolve = (value) => {// 只有状态是等待,才执行状态修改if (this.status === PENDING) {// 状态修改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// ==== 新增 ====// 判断成功回调是否存在,如果存在就调用this.onFulfilledCallback && this.onFulfilledCallback(value);}
}

多次调用同一个promise的then

// test.jsconst MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {setTimeout(() => {resolve('success')}, 2000); 
})promise.then(value => {console.log(1)console.log('resolve', value)
})promise.then(value => {console.log(2)console.log('resolve', value)
})promise.then(value => {console.log(3)console.log('resolve', value)
})
//单个回调:3
resolve success
//回调队列:
1
resolve success
2
resolve success
3
resolve success

1.缓存成功与失败回调 队列

// MyPromise.js// 存储成功回调函数
// onFulfilledCallback = null;
onFulfilledCallbacks = [];
// 存储失败回调函数
// onRejectedCallback = null;
onRejectedCallbacks = [];

2.pengding时,then()收集依赖,将成功/失败回调放入成功/失败队列

// MyPromise.jsthen(onFulfilled, onRejected) {// 判断状态if (this.status === FULFILLED) {// 调用成功回调,并且把值返回onFulfilled(this.value);} else if (this.status === REJECTED) {// 调用失败回调,并且把原因返回onRejected(this.reason);} else if (this.status === PENDING) {// ==== 新增 ====// 因为不知道后面状态的变化,这里先将成功回调和失败回调存储起来// 等待后续调用this.onFulfilledCallbacks.push(onFulfilled);this.onRejectedCallbacks.push(onRejected);}
}

3.触发resolve/reject,从成功/失败队列中取出回调依次执行

// MyPromise.js// 更改成功后的状态
resolve = (value) => {// 只有状态是等待,才执行状态修改if (this.status === PENDING) {// 状态修改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// ==== 新增 ====// resolve里面将所有成功的回调拿出来执行while (this.onFulfilledCallbacks.length) {// Array.shift() 取出数组第一个元素,然后()调用,shift不是纯函数,取出后,数组将失去该元素,直到数组为空this.onFulfilledCallbacks.shift()(value)}}
}

then链式调用:返回一个 Promise 对象

以fulfilled为例,其他同理

// MyPromise.jsclass MyPromise {...then(onFulfilled, onRejected) {// 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去const promise2 = new MyPromise((resolve, reject) => {// 这里的内容在执行器中,会立即执行if (this.status === FULFILLED) {// 获取成功回调函数的执行结果const x = onFulfilled(this.value);// 传入 resolvePromise 集中处理resolvePromise(x, resolve, reject);} ...}) return promise2;}
}function resolvePromise(x, resolve, reject) {// 判断x是不是 MyPromise 实例对象if(x instanceof MyPromise) {// 执行 x,调用 then 方法,目的是将其状态变为 fulfilled 或者 rejected// x.then(value => resolve(value), reason => reject(reason))// 简化之后x.then(resolve, reject)} else{// 普通值resolve(x)}
}

then返回自己时,抛错循环调用

// test.jsconst promise = new Promise((resolve, reject) => {resolve(100)
})
const p1 = promise.then(value => {console.log(value)return p1
})

function resolvePromise(promise2, x, resolve, reject) {// 如果相等了,说明return的是自己,抛出类型错误并返回if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}...
}
等返回的promise初始化好:queueMicrotask微任务

// MyPromise.jsclass MyPromise {......then(onFulfilled, onRejected) {const promise2 = new MyPromise((resolve, reject) => {if (this.status === FULFILLED) {// 创建一个微任务等待 promise2 完成初始化queueMicrotask(() => {// 获取成功回调函数的执行结果const x = onFulfilled(this.value);// 传入 resolvePromise 集中处理resolvePromise(promise2, x, resolve, reject);})  } ...}) return promise2;}
}

捕获错误

 try {异步操作
} catch (error) {reject(error)
}  

executor错误

// MyPromise.jsconstructor(executor){// ==== 新增 ====// executor 是一个执行器,进入会立即执行// 并传入resolve和reject方法try {executor(this.resolve, this.reject)} catch (error) {// 如果有错误,就直接执行 rejectthis.reject(error)}
}

then错误

// MyPromise.jsthen(onFulfilled, onRejected) {// 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去const promise2 = new MyPromise((resolve, reject) => {// 判断状态if (this.status === FULFILLED) {// 创建一个微任务等待 promise2 完成初始化queueMicrotask(() => {try {// 获取成功回调函数的执行结果const x = onFulfilled(this.value);// 传入 resolvePromise 集中处理resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error)}  })  } ...}) return promise2;
}

then([onFulfilled, onRejected])参数可选

then 穿透:忽略非函数参数,非函数会同步执行

Promise.resolve(1).then(2)//传入值.then(Promise.resolve(3))//传入promise对象.then(console.log)//传入函数
1

Promise.resolve().then(new Promise(r => {setTimeout(() => {r(console.log(1))}, 1000)})).then(new Promise(r => {setTimeout(() => {r(console.log(2))}, 1000)})).then(new Promise(r => {setTimeout(() => {r(console.log(3))}, 1000)}))
延迟1秒后,打印123

不同于下面

// MyPromise.jsthen(onFulfilled, onRejected) {// 如果不传,就使用默认函数onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};// 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去const promise2 = new MyPromise((resolve, reject) => {......
}

静态调用resolve、reject

// MyPromise.jsMyPromise {......// resolve 静态方法static resolve (parameter) {// 如果传入 MyPromise 就直接返回if (parameter instanceof MyPromise) {return parameter;}// 转成常规方式return new MyPromise(resolve =>  {resolve(parameter);});}// reject 静态方法static reject (reason) {return new MyPromise((resolve, reject) => {reject(reason);});}
}

完整版

// MyPromise.js// 先定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';// 新建 MyPromise 类
class MyPromise {constructor(executor){// executor 是一个执行器,进入会立即执行// 并传入resolve和reject方法try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}// 储存状态的变量,初始值是 pendingstatus = PENDING;// 成功之后的值value = null;// 失败之后的原因reason = null;// 存储成功回调函数onFulfilledCallbacks = [];// 存储失败回调函数onRejectedCallbacks = [];// 更改成功后的状态resolve = (value) => {// 只有状态是等待,才执行状态修改if (this.status === PENDING) {// 状态修改为成功this.status = FULFILLED;// 保存成功之后的值this.value = value;// resolve里面将所有成功的回调拿出来执行while (this.onFulfilledCallbacks.length) {// Array.shift() 取出数组第一个元素,然后()调用,shift不是纯函数,取出后,数组将失去该元素,直到数组为空this.onFulfilledCallbacks.shift()(value)}}}// 更改失败后的状态reject = (reason) => {// 只有状态是等待,才执行状态修改if (this.status === PENDING) {// 状态成功为失败this.status = REJECTED;// 保存失败后的原因this.reason = reason;// resolve里面将所有失败的回调拿出来执行while (this.onRejectedCallbacks.length) {this.onRejectedCallbacks.shift()(reason)}}}then(onFulfilled, onRejected) {const realOnFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;const realOnRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};// 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去const promise2 = new MyPromise((resolve, reject) => {const fulfilledMicrotask = () =>  {// 创建一个微任务等待 promise2 完成初始化queueMicrotask(() => {try {// 获取成功回调函数的执行结果const x = realOnFulfilled(this.value);// 传入 resolvePromise 集中处理resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error)} })  }const rejectedMicrotask = () => { // 创建一个微任务等待 promise2 完成初始化queueMicrotask(() => {try {// 调用失败回调,并且把原因返回const x = realOnRejected(this.reason);// 传入 resolvePromise 集中处理resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error)} }) }// 判断状态if (this.status === FULFILLED) {fulfilledMicrotask() } else if (this.status === REJECTED) { rejectedMicrotask()} else if (this.status === PENDING) {// 等待// 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来// 等到执行成功失败函数的时候再传递this.onFulfilledCallbacks.push(fulfilledMicrotask);this.onRejectedCallbacks.push(rejectedMicrotask);}}) return promise2;}// resolve 静态方法static resolve (parameter) {// 如果传入 MyPromise 就直接返回if (parameter instanceof MyPromise) {return parameter;}// 转成常规方式return new MyPromise(resolve =>  {resolve(parameter);});}// reject 静态方法static reject (reason) {return new MyPromise((resolve, reject) => {reject(reason);});}
}function resolvePromise(promise2, x, resolve, reject) {// 如果相等了,说明return的是自己,抛出类型错误并返回if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}// 判断x是不是 MyPromise 实例对象if(x instanceof MyPromise) {// 执行 x,调用 then 方法,目的是将其状态变为 fulfilled 或者 rejected// x.then(value => resolve(value), reason => reject(reason))// 简化之后x.then(resolve, reject)} else{// 普通值resolve(x)}
}module.exports = MyPromise;

Promise A+ 规范版的resolvePromise

要求判断 x 是否为 object 或者 function,满足则接着判断 x.then 是否存在,这里可以理解为判断 x 是否为 promise,这里都功能实际与我们手写版本中 x instanceof MyPromise 功能相似

// MyPromise.jsfunction resolvePromise(promise, x, resolve, reject) {// 如果相等了,说明return的是自己,抛出类型错误并返回if (promise === x) {return reject(new TypeError('The promise and the return value are the same'));}if (typeof x === 'object' || typeof x === 'function') {// x 为 null 直接返回,走后面的逻辑会报错if (x === null) {return resolve(x);}let then;try {// 把 x.then 赋值给 then then = x.then;} catch (error) {// 如果取 x.then 的值时抛出错误 error ,则以 error 为据因拒绝 promisereturn reject(error);}// 如果 then 是函数if (typeof then === 'function') {let called = false;try {then.call(x, // this 指向 x// 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)y => {// 如果 resolvePromise 和 rejectPromise 均被调用,// 或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用// 实现这条需要前面加一个变量 calledif (called) return;called = true;resolvePromise(promise, y, resolve, reject);},// 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promiser => {if (called) return;called = true;reject(r);});} catch (error) {// 如果调用 then 方法抛出了异常 error:// 如果 resolvePromise 或 rejectPromise 已经被调用,直接返回if (called) return;// 否则以 error 为据因拒绝 promisereject(error);}} else {// 如果 then 不是函数,以 x 为参数执行 promiseresolve(x);}} else {// 如果 x 不为对象或者函数,以 x 为参数执行 promiseresolve(x);}
}

catch

//catch方法其实就是执行一下then的第二个回调
catch(rejectFn) {return this.then(undefined, rejectFn)
}

finally

由于无法知道promise的最终状态,所以finally的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况

 finally(callBack) {return this.then(callBack, callBack)}

并发请求

模板

  /*** @param {iterable} promises 一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入* @returns */
static 并发(promises) {
// 参数校验
if (Array.isArray(promises)) {let result = []; // 存储结果let count = 0; // 计数器if (promises.length === 0) {
// 如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promisereturn resolve(promises);//C. 返回一个 已失败(already rejected) 状态的 Promise。return reject(new AggregateError('All promises were rejected'));}return new myPromise((resolve, reject) => {promises.forEach((item, index) => {myPromise.resolve(item).then(value => {count++;// 每个promise执行的结果存储在result中//A.记录所有reject/fulfilled,需要区分状态result[index] = {status: 'fulfilled',value}//B.只记录fulfilledresult[index] = value// 如果所有的 Promise 都已经处理完毕,就调用 resolve(result)count === promises.length && resolve(result);//C.只要一个成功resolve(value);},reason => {//A.记录所有rejectcount++;result[index] = {status: 'rejected',reason}count === promises.length && resolve(result);//B.一旦rejectreject(reason);     //C.全rejectcount++;errors.push(reason);//AggregateError是 Error 的一个子类,用于把单一的错误集合在一起。count === promises.length && reject(new AggregateError(errors));})})} else {return reject(new TypeError('Argument is not iterable'))
}}

all

/**
* 如果传入的 promise 中有一个失败(rejected),
* Promise.all 异步地将失败的那个结果给失败状态的回调函数,而不管其它 promise 是否完成
*/     
static all(promises) {
return new myPromise((resolve, reject) => {promises.forEach((item, index) => {myPromise.resolve(item).then(value => {count++;// 每个promise执行的结果存储在result中result[index] = value;// 如果所有的 Promise 都已经处理完毕,就调用 resolve(result)count === promises.length && resolve(result);},reason => {reject(reason);                         })})
}

allSettled

static allSettled(promises) {
return new myPromise((resolve, reject) => {promises.forEach((item, index) => {myPromise.resolve(item).then(value => {count++;// 每个promise执行的结果存储在result中//A.记录所有reject/fulfilled,需要区分状态result[index] = {status: 'fulfilled',value}// 如果所有的 Promise 都已经处理完毕,就调用 resolve(result)count === promises.length && resolve(result);},reason => {//A.记录所有rejectcount++;result[index] = {status: 'rejected',reason}count === promises.length && resolve(result);           })})
}

any

static any(promises){return new myPromise((resolve, reject) => {promises.forEach((item, index) => {myPromise.resolve(item).then(value => {//C.只要一个成功resolve(value);},reason => {//C.全rejectcount++;errors.push(reason);//AggregateError是 Error 的一个子类,用于把单一的错误集合在一起。count === promises.length && reject(new AggregateError(errors));})})
}

race

//race方法(返回最早执行完的promise结果,无论成功与否)
Promise.race = function(promises){return new myPromise((resolve, reject) => {// 如果传入的迭代promises是空的,则返回的 promise 将永远等待。if (promises.length > 0) {promises.forEach(item => {myPromise.resolve(item).then(resolve, reject);})}}})

手写实现 Promise 全部实例方法和静态方法,来看看 Promise.all、Promise.race 和 Promise.any 都是怎么实现的 - 掘金

从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节 - 掘金

相关文章:

手写promise A+、catch、finally、all、allsettled、any、race

目录 手写promise 同步版 1.Promise的构造方法接收一个executor()&#xff0c;在new Promise()时就立刻执行executor回调 2.executor()内部的异步任务被放入宏/微任务队列&#xff0c;等待执行 3.状态与结果的管理 状态只能变更一次 4.then()调用成功/失败回调 catch是…...

【原神游戏开发日志1】缘起

【原神游戏开发日志1】缘起 版权声明 本文为“优梦创客”原创文章&#xff0c;您可以自由转载&#xff0c;但必须加入完整的版权声明 文章内容不得删减、修改、演绎 相关学习资源见文末 大家好&#xff0c;最近看到原神在TGA上频频获奖&#xff0c;作为一个14年经验的游戏开…...

leetcode5 最长公共前缀三种python解法

14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示…...

对小程序的初了解

WXML和HTML的区别 标签名称不同 HTML&#xff1a;div、a、span、img WXML&#xff1a;view、text、image、navigator 属性节点不同 <a href"#">超链接</a> <navigator url"/pages/home/home"></navigator> 提供了类似vue的…...

QLineEdit 的 InputMask掩码

QLineEdit 的 InputMask掩码 A&#xff1a;只能输入字母&#xff0c;且不可省略 a&#xff1a;只能输入字母&#xff0c;可以省略 N&#xff1a;只能输入 字母和数字&#xff0c;且不可省略 n&#xff1a;只能输入 字母和数字&#xff0c;可以省略 X&#xff1a;可以输入任意字…...

关于队列的简单理解

1.队列(Queue) 1.1 关于队列 队列 &#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c; 队列具有先进先出 FIFO(First In First Out)的操作特性&#xff08;队列是个接口&#xff09;&#xff1b; 入队列&#x…...

加密市场进入牛初阶段?一场新的造富效应即将拉开帷幕!

周一(12月4日)&#xff0c;比特币一度上涨至42000美元&#xff0c;创下自2022年4月以来的最高水平。从目前比特币的走势来看&#xff0c;加密市场无疑已然进入到牛初阶段。 在牛市初期&#xff0c;确实存在人们不相信牛市到来的情况。由于在熊市中亏损的心理阻碍和对市场进一步…...

Superset基础入门

1 Superset概述 Apache Superset 是一个现代的数据探索和可视化平台。它功能强大且十分易用&#xff0c;可对接 各种数据源&#xff0c;包括很多现代的大数据分析引擎&#xff0c;拥有丰富的图表展示形式&#xff0c;并且支持自定义 仪表盘。 2 Superset安装 Superset 是由 P…...

【泛微ecology】将多个字段的数据合并到一个字段

doFieldSQL("select concat(concat(sqr,,),sy) as c from formtable_main_2 where requestid $requestid$ ")...

WebSocket入门介绍及编程实战

HTTP的限制 全双工和半双工&#xff1a; 全双工&#xff1a;全双工&#xff08;Full Duplex&#xff09;是允许数据在两个方向上同时传输。 半双工&#xff1a;半双工&#xff08;Half Duplex&#xff09;是允许数据在两个方向上传输&#xff0c;但是同一个时间段内只允许一个…...

vue3里面生命周期的使用

前言&#xff1a; vue2里面的生命周期和vue3生命周期是非常的相似的&#xff0c;我们通过访问生命周期钩子来处理不同场景之间的应用。 生命周期钩子的函数定义&#xff1a;每一个Vue组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如数据侦听&#xff0c;编译模…...

在python的Scikit-learn库中,可以使用train_test_split函数来划分训练集和测试集。

文章目录 一、在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试集总结 一、在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试集 在Scikit-learn库中&#xff0c;可以使用train_test_split函数来划分训练集和测试…...

外包干了2个月,技术明显退步了...

先说一下自己的情况&#xff0c;大专生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近5年的功能测试&#xff0c;今年11月份&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…...

数据结构:链表应用:第9关:删除链表中满足区间值的结点

任务描述编程要求 输入输出测试说明来源 任务描述 本关任务&#xff1a;利用单链表表示一个递增的整数序列&#xff0c;删除链表中值大于等于mink且小于等于maxk的所有元素&#xff08;mink和maxk是给定的两个参数&#xff0c;其值可以和表中的元素相同&#xff0c;也可以不同…...

了解 ignore_above 参数对 Elasticsearch 中磁盘使用的影响

在 Elasticsearch 中&#xff0c;ignore_above 参数允许你忽略&#xff08;而不是索引&#xff09;长于指定长度的字符串。 这对于限制字段的大小以避免性能问题很有用。 在本文中&#xff0c;我们将探讨 “ignore_above” 参数如何影响 Elasticsearch 中字段的大小&#xff0c…...

C#中的async/await异步编程模型

前言 当谈到异步编程时&#xff0c;C#中的async/await是一个强大且方便的工具。它使得编写并发和异步操作变得更加简单和可读&#xff0c;同时提供良好的可维护性。本文将详细解释async/await的使用&#xff0c;以及如何在C#中有效地利用它来实现异步操作。 目录 前言1. async…...

【原创】提升MybatisPlus分页便捷性,制作一个属于自己的分页插件,让代码更加优雅

前言 MybatisPlus的分页插件有一点非常不好&#xff0c;就是要传入一个IPage&#xff0c;别看这个IPage没什么大不了的&#xff0c;最多多写一两行代码&#xff0c;可这带来一个问题&#xff0c;即使用xml的查询没法直接取对象里面变量的值了&#xff0c;得Param指定xml中的变…...

pythonselenium自动化测试实战项目

说明&#xff1a;本项目采用流程控制思想&#xff0c;未引用unittest&pytest等单元测试框架 一.项目介绍 目的 测试某官方网站登录功能模块可以正常使用 用例 1.输入格式正确的用户名和正确的密码&#xff0c;验证是否登录成功&#xff1b; 2.输入格式正确的用户名和不…...

智能优化算法应用:基于瞬态优化算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于瞬态优化算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于瞬态优化算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.瞬态优化算法4.实验参数设定5.算法结果6.参考…...

springMVC 三大组件解析

springMVC组件概述 DispatcherServlet&#xff08;调度器Servlet&#xff09;&#xff1a; DispatcherServlet 是 Spring MVC 的前端控制器&#xff08;Front Controller&#xff09;。它负责接收来自客户端的请求&#xff0c;然后将请求分发给相应的处理器&#xff08;Control…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...