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

news2024/11/24 5:03:17

目录

手写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){
  ...
  }

  // 储存状态的变量,初始值是 pending
  status = 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.js

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

异步版

// test.js

const 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.js

then(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.js

const 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.js

then(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.js

class 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.js

const 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.js

class 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.js

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

then错误

// MyPromise.js

then(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.js

then(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.js

MyPromise {
  ......
  // 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)
    }
  }

  // 储存状态的变量,初始值是 pending
  status = 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.js

function 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 为据因拒绝 promise
      return reject(error);
    }

    // 如果 then 是函数
    if (typeof then === 'function') {
      let called = false;
      try {
        then.call(
          x, // this 指向 x
          // 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
          y => {
            // 如果 resolvePromise 和 rejectPromise 均被调用,
            // 或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
            // 实现这条需要前面加一个变量 called
            if (called) return;
            called = true;
            resolvePromise(promise, y, resolve, reject);
          },
          // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
          r => {
            if (called) return;
            called = true;
            reject(r);
          });
      } catch (error) {
        // 如果调用 then 方法抛出了异常 error:
        // 如果 resolvePromise 或 rejectPromise 已经被调用,直接返回
        if (called) return;

        // 否则以 error 为据因拒绝 promise
        reject(error);
      }
    } else {
      // 如果 then 不是函数,以 x 为参数执行 promise
      resolve(x);
    }
  } else {
    // 如果 x 不为对象或者函数,以 x 为参数执行 promise
    resolve(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)状态的 Promise
         return 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.只记录fulfilled
                    result[index] = value
                 // 如果所有的 Promise 都已经处理完毕,就调用 resolve(result)
                 count === promises.length && resolve(result);
                 //C.只要一个成功
                 resolve(value);
                 },
                 reason => {
                 //A.记录所有reject
                 count++;
                 result[index] = {
                               status: 'rejected',
                               reason
                                }
                 count === promises.length && resolve(result);
                 //B.一旦reject
                 reject(reason);     
                 //C.全reject
                 count++;
                 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.记录所有reject
                 count++;
                 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.全reject
                 count++;
                 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 实现细节 - 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1265740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单测试大语言模型 Yi-34B 的中日英能力

简单测试大语言模型 Yi-34B 的中日英能力 0. 背景1. 中文测试2. 日文测试3. 英文测试 0. 背景 简单测试一下C-Eval 排行榜第一&#xff08;20231129时点&#xff09;的 Yi-34B 的中日英能力&#xff0c; 1. 中文测试 问题1&#xff0c;回答正确。 问题2&#xff0c;回答正确。…

monorepo多项目管理主流实现方式:1.learn + yarn/npm workspace 2.pnpm

npm域级包 随着npm包越来越多&#xff0c;而且包名也只能是唯一的&#xff0c;如果一个名字被别人占了&#xff0c;那你就不能再使用这个名字&#xff1b;假设我想要开发一个utils包&#xff0c;但是张三已经发布了一个utils包&#xff0c;那我的包名就不能叫utils了&#xff…

仿美团外卖源码/在线外卖平台源码PHP/支持多商户+多样化配送费+本土外卖+支持第三方配送

源码简介&#xff1a; 进云仿美团外卖源码&#xff0c;作为外卖平台源码&#xff0c;它不仅支持多商户、多样化配送费、本土外卖&#xff0c;还支持第三方配送。 进云仿美团外卖源码是一个进云源生插件&#xff0c;支持多商户多样化配送费模式本土外卖平台支持第三方配送&…

浅谈安科瑞网络电力仪表在斯里兰卡某项目的应用

摘要&#xff1a;安科瑞APM系列网络仪表适用于高低压柜&#xff0c;进线以及出线处的全电量测量及监测。 Absrtact: APM series of network power meter are suitable for full power measurement and monitoring of high and low voltage cabinets, incoming and outgoing li…

简洁、高效、灵活:探索 Spring 同级别的编程框架

文章目录 GrailsMicronautVert.xQuarkusPlay FrameworkDropwizard 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 作为一个Java开发者&#xff0c;Spring框架应该基本上都用过的&#x…

Docker容器网络模式

1.none网络 1&#xff09;使用默认网络模式创建一个BusyBox容器&#xff0c;用于对比none网络模式&#xff1b; 测试网络&#xff0c;可以正常连接外网。 2&#xff09;再创建一个none网络模式的BusyBox容器&#xff1b; 测试网络连接&#xff0c;无法连接外网。 总结&#x…

C++:C++11新特性---右值引用

文章目录 初始化方式显示查看类型initializer_listdecltype左值引用和右值引用move左右值引用的场景 万能引用和完美转发 本篇总结C11新特性 初始化方式 C11对参数列表的初始化有了更明确的定义&#xff0c;可以这样进行定义 // 列表初始化 void test1() {// 旧版本int x 0…

前端大屏适配几种方案

记录一下前端大屏的几种适配方案。 我们是1920*1080的设计稿。 目录 目录 一、方案一&#xff1a;remfont-size 二、方案二&#xff1a;vw&#xff08;单位&#xff09; 三、方案三&#xff1a;scale&#xff08;缩放&#xff09;强烈推荐 1、根据宽度比率进行缩放 2、动…

点云凹凸缺陷检测 最高层点云 点云聚类

文章目录 0. 数据说明1. 凹凸缺陷基本内容2. 详细检测思路 结果&#xff1a; 0. 数据说明 如上图所示&#xff0c;需要检测的内容为红色框内标出的缺陷部分。简单示例如下红色线条。 但是&#xff0c;由于噪声的影响&#xff0c;点云的平面度并不好&#xff0c;且横梁边缘处存…

4/150:寻找两个正序数组的中位数⭐

题目&#xff1a;寻找两个正序数组的中位数 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 题解1&#xff1a;暴力 暴力思路简介&#xff0c;…

在数据库中进行表内容的修改(MYSQL)

根据表中内容&#xff0c;用命令语句创建数据库&#xff0c;表格&#xff0c;以及插入&#xff0c;修改&#xff0c;删除表格中的内容。 创建数据库&#xff1a;zrzy mysql> create database zrzy; 引用zrzy数据库&#xff1a; mysql> use zrzy; 创建student_info表&…

蓝桥杯day02——移动机器人

1.题目 有一些机器人分布在一条无限长的数轴上&#xff0c;他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时&#xff0c;它们以每秒钟一单位的速度开始移动。 给你一个字符串 s &#xff0c;每个字符按顺序分别表示每个机器人移动的方向。L 表…

随时随地,打开浏览器即可体验的在线PS编辑器

即时设计 即时设计是国产的专业级 UI 设计工具&#xff0c;不限平台不限系统&#xff0c;在浏览器打开即用&#xff0c;能够具备 Photoshop 的设计功能&#xff0c;钢笔、矢量编辑、矩形工具、布尔运算等设计工具一应俱全&#xff0c;是能够在线使用的 Photoshop 免费永久工具…

Redis实战命令

实战命令 单值缓存 set key value get key 对象缓存 &#xff08;1&#xff09;set user:1 value(json格式) &#xff08;2&#xff09;mset user:1:name junfeng user:1:age 18 mget user:1:name user:1:age 分布式锁 分布式锁解决了什么问题&#xff1f; 分布式锁解…

63 权限提升-Linux脏牛内核漏洞SUID信息收集

目录 演示案例:Linux提权自动化脚本利用-4个脚本Linux提权SUID配合脚本演示-AliyunLinux提权本地配合内核漏洞演示-MozheLinux提权脏牛内核漏洞演示-Aliyun&#xff0c;Vulnhub涉及资源: linux提权相对windows提权方法相对少一些&#xff0c;linux提权方法相对来讲有七八种方式…

WIFI HaLow技术引领智能互联,打破通信限制

在过去十年里&#xff0c;WIFI技术已在家庭和企业中建立起了庞大的网络&#xff0c;连接了数十亿智能互联设备&#xff0c;促进了信息的迅速传递。然而&#xff0c;当前的WIFI标准存在一些挑战&#xff0c;包括协议范围的限制和整体功能的受限&#xff0c;导致在较远距离进行通…

Python开发——工具篇 Pycharm的相关配置,Python相关操作 持续更新

前言 本篇博客是python开发的工具篇相关&#xff0c;介绍pycharm的使用和相关配置&#xff0c;收录python的相关操作&#xff0c;比如如何启动jupyter。 目录 前言引出Pycharmpycharm如何不同等级日志显示不同颜色设置不同pycharm的python环境 Python操作如何启动Jupyter 总结…

SpringBoot : ch11 整合RabbitMQ

前言 在当今的互联网时代&#xff0c;消息队列成为了构建高可靠、高性能系统的重要组件之一。RabbitMQ作为一个可靠、灵活的消息中间件&#xff0c;被广泛应用于各种分布式系统中。 本篇博客将介绍如何使用Spring Boot整合RabbitMQ&#xff0c;实现消息的发送和接收。通过这种…

【测试开发】web自动化测试框架需求设计 !

1、实现目的 基于BS架构&#xff0c;模拟用户&#xff08;鼠标、键盘&#xff09;操作&#xff0c;达到快速、重复执行测试用例&#xff1b; 便于回归测试&#xff0c;快速覆盖主线用例或功能&#xff1b; 线上或线下巡检测试&#xff0c;结合持续集成&#xff0c;及时发现运…

万户协同办公平台ezoffice SendFileCheckTemplateEdit.jsp接口存在SQL注入漏洞 附POC

@[toc] 万户协同办公平台ezoffice SendFileCheckTemplateEdit.jsp接口存在SQL注入漏洞 附POC 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文…