JS详解-手写Promise!!!

news2024/11/20 18:21:49

前言:

针对js的深入理解,作者学习并撰写以下文章,由于理解认知有限难免存在偏差,请大家指正!所有定义来自mdn。

Promise介绍:

        对象表示异步操作最终的完成(或失败)以及其结果值.

        描述:

一个 Promise 是一个代理,它代表一个在创建 promise 时不一定已知的值。它允许你将处理程序与异步操作的最终成功值或失败原因关联起来。这使得异步方法可以像同步方法一样返回值:异步方法不会立即返回最终值,而是返回一个 promise,以便在将来的某个时间点提供该值。

一个 Promise 必然处于以下几种状态之一:

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败。

一个待定的 Promise 最终状态可以是已兑现并返回一个值,或者是已拒绝并返回一个原因(错误)。当其中任意一种情况发生时,通过 Promise 的 then 方法串联的处理程序将被调用。如果绑定相应处理程序时 Promise 已经兑现或拒绝,这处理程序将被立即调用,因此在异步操作完成和绑定处理程序之间不存在竞态条件。

如果一个 Promise 已经被兑现或拒绝,即不再处于待定状态,那么则称之为已敲定(settled)

Promise.resolve:

        Promise.resolve() 静态方法将给定的值转换为一个 Promise。如果该值本身就是一个 Promise,那么该 Promise 将被返回;如果该值是一个 thenable 对象,Promise.resolve() 将调用其 then() 方法及其两个回调函数;否则,返回的 Promise 将会以该值兑现。

构造MyPromise函数:

   // 构造函数
        // 定义类
        class MyPromise {
            // 添加构造函数
            constructor(func){
                // 定义resolve和reject方法
                const resolve = (value) => {
                    console.log('resolve执行:',value)
                    // // 判断状态是否为pending
                    // if(this.status === 'pending'){
                    //     // 修改状态为fulfilled
                    //     this.status = 'fulfilled'
                    //     // 保存成功的值
                    //     this.value = value
                    //     // 执行成功的回调函数
                    //     this.onFulfilledCallbacks.forEach(fn => fn())
                    // }
                }
                const reject = (value) => {
                    console.log('reject执行:',value)
                }
                // 初始化状态
                func(resolve,reject)
            }
        }

        // 测试代码
        const p = new MyPromise((resolve,reject) => {
            console.log('执行器函数执行')
            resolve('成功')
            reject('失败')
        })

状态和原因:

含bug代码

    <h2>状态及原因</h2>
    <script>
        // 1、添加原生Promise状态fulfilled/pending/rejected
        // 2、添加原生Promise原因resolve/reject
        // 3、调整resolve/reject方法
        // 4、状态不可逆
        // 为了方便和规范起见命名MyPromise的状态
        const PENDING = 'pending'
        const FULFILLED = 'fulfilled'
        const REJECTED = 'rejected'

        class MyPromise {
            // 状态初始化
            status = PENDING
            result = undefined
            // 添加构造函数
            constructor(func){
                // 定义resolve和reject方法
                const resolve = (value) => {
                    // 修改状态并记录原因
                    this.status = FULFILLED
                    this.result = value
                }
                const reject = (value) => {
                    // 修改状态并记录原因
                    this.status = REJECTED
                    this.result = value
                }
                // 初始化状态
                func(resolve,reject)
            }
        }

        // 测试代码
        const p = new MyPromise((resolve,reject) => {
            resolve('成功')
            reject('失败')
        })

在未添加自定义的状态不可逆时代码有误还是会按照js从上向下执行原则最后改变pending从sucees to fail.

接下来我们开始处理不可逆属性:

 // 定义resolve和reject方法
                const resolve = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = FULFILLED
                        this.result = result
                    }
                }
                const reject = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = REJECTED
                        this.result = result
                }
                // 初始化状态
                func(resolve,reject)
                }

then方法:

成功失败回调:

tips:被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。

      const PENDING = 'pending'
        const FULFILLED = 'fulfilled'
        const REJECTED = 'rejected'

        class MyPromise {
            // 状态初始化
            // 添加状态
            status = PENDING
            // 添加原因
            result = undefined
            // 添加构造函数
            constructor(func){
                // 定义resolve和reject方法
                const resolve = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = FULFILLED
                        this.result = result
                    }
                }
                const reject = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = REJECTED
                        this.result = result
                }
            }
                // 初始化状态
                func(resolve,reject)

            }
        then(onFulfilled,onRejected){
            // 根据mdn知道需要判断回调函数是否为函数,如果不是需要处理
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
            onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
            // 判断状态
            if(this.status === FULFILLED){
                onFulfilled(this.result)
            }
            else if(this.status === REJECTED){
                onRejected(this.result)
            }
        }
        }
        // 测试代码
        const p = new MyPromise((resolve,reject) => {
           // resolve('success')
            reject('fail')
        })

        p.then((res) => {
            console.log('成功回调',res)
        },(err) => {
            console.log('失败抛出错误',err)
        })

异步多次调用:
 // 定义常量
        const PENDING = 'pending'
        const FULFILLED = 'fulfilled'
        const REJECTED = 'rejected'

        class MyPromise {
            // 状态初始化
            // 添加状态
            status = PENDING
            // 添加原因
            result = undefined

            // 私有属性handlers
            #handlers = [] //[{onFulfilled,onRejected}...]
            // 添加构造函数
            constructor(func){
                // 定义resolve和reject方法
                const resolve = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = FULFILLED
                        this.result = result
                        // 调用成功回调函数
                        this.#handlers.forEach(({onFulfilled}) => {
                            onFulfilled(result)
                        })
                    }
                }
                const reject = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = REJECTED
                        this.result = result
                        // 调用失败回调函数
                        this.#handlers.forEach(({onRejected}) => {
                            onRejected(result)
                        })
                }
            }
                // 初始化状态
                func(resolve,reject)

            }
        then(onFulfilled,onRejected){
            // 根据mdn知道需要判断回调函数是否为函数,如果不是需要处理
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
            onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
            // 判断状态
            // 同步调用
            if(this.status === FULFILLED){
                onFulfilled(this.result)
            }
            else if(this.status === REJECTED){
                onRejected(this.result)
            }//异步和多次调用
            else if(this.status === PENDING){
                // 添加回调函数
               this.#handlers.push({onFulfilled,onRejected})
            }
        }
        }
        // 测试代码
        const p = new MyPromise((resolve,reject) => {
           setTimeout(() => {
               resolve('success')
               reject('fail')
           },1000)
        })

        p.then((res) => {
            console.log('then1',res)
        },(err) => {
            console.log('then1',err)
        })

        p.then((res) => {
            console.log('then2',res)
        },(err) => {
            console.log('then2',err)
        })

异步任务:

核心api:
   // 异步任务 queueMicrotask
        console.log('start')
        queueMicrotask(() => {
            console.log('queueMicrotask')
        })
        console.log('end')
        // 异步任务 MutationObserver
        // 1、创建观察器,并传入回调函数
        const obs = new MutationObserver(() => {
            console.log('mutationsList')
        })
        // 2、创建元素,并添加监听
        const divNode = document.createElement('div')
        // 参数1dom节点,参数2配置对象childList:true表示监听子节点变化
        obs.observe(divNode,{childList:true})
        // 3、修改元素内容,观察器触发MutationObserver
        divNode.innerText = 'hello'
函数封装:
// 封装函数分别使用queueMicrotask和MutationObserver setTimeout实现异步任务
        function runAsyncTask(callback){
            // 使用queueMicrotask
            if(typeof queueMicrotask === 'function')
            {
                queueMicrotask(callback)
            }else if (typeof MutationObserver === 'function'){
                // 使用MutationObserver
                const observer = new MutationObserver(callback)
                const nodeDiv = document.createTextNode('div')
                observer.observe(nodeDiv,{childList:true})
                node.innerText = 'hello'
            }else{
            setTimeout((callback) ,0)
            }
        }

对then中的回调方法增加异步属性

        // 使用封装的异步函数
        then(onFulfilled,onRejected){
            // 根据mdn知道需要判断回调函数是否为函数,如果不是需要处理
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
            onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
            // 判断状态
            // 同步调用
            if(this.status === FULFILLED){
               runAsyncTask(() => {
                   onFulfilled(this.result)
               })
            }
            else if(this.status === REJECTED){
                runAsyncTask(() => {
                    onRejected(this.result)
                })
            }//异步和多次调用
            else if(this.status === PENDING){
                // 添加回调函数
               this.#handlers.push({
                onFulfilled:()=>{
                    runAsyncTask(() => {
                        onFulfilled(this.result)
                    })
                }
                ,
                onRejected:()=>{
                    runAsyncTask(() => {
                        onRejected(this.result)
                    })
                }
            })
            }
        }

成功实现异步调用

链式编程:

获取返回值:
处理返回值和处理异常:

使用try-catch进行返回值处理和异常捕获,同时在then中内嵌的promise调用和回调函数的使用完成对上一个then的返回值的捕获和返回。

 // 1、返回新的promise对象 传入的函数是立刻调用的
            const p2 = new MyPromise((resolve,reject)=>{
                 // 判断状态
            // 同步调用
            if(this.status === FULFILLED){
               runAsyncTask(() => {
                // 2、获取返回值
                 try {
                    const x = onFulfilled(this.result)
                  // 2.1处理返回值
                  resolve(x)
                 } catch (error) {
                    reject(error)
                 }
               })
            }
            else if(this.status === REJECTED){
                runAsyncTask(() => {
                    onRejected(this.result)
                })
            }//异步和多次调用
            else if(this.status === PENDING){
                // 添加回调函数
               this.#handlers.push({
                onFulfilled:()=>{
                    runAsyncTask(() => {
                        onFulfilled(this.result)
                    })
                }
                ,
                onRejected:()=>{
                    runAsyncTask(() => {
                        onRejected(this.result)
                    })
                }
            })
            }
            })
           return p2

处理返回promise:

tips:instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

x为返回的promise实例

runAsyncTask(() => {
                // 2、获取返回值
                 try {
                   const x = onFulfilled(this.result)
                   if(x instanceof MyPromise){
                       x.then(res => resolve(res),err => reject(err))
                   }
                   else{resolve(x)}
                 } catch (error) {
                    reject(error)
                 }
               })
// 测试代码
        // console.log('start')
        const p = new MyPromise((resolve,reject) => {
            resolve(1)  
            //reject('fail')
        })
        p.then((res)=>{
            return new MyPromise((resolve,reject) => {
                resolve(2)
            })
        }).then((res) => {
           console.log('p2',res)
        },(err) => {
            console.log('p2',err)
        })

获取重复调用:

利用原生Promise报错模仿写自己的Promise返回相同值(Promise)的报错

Chaining cycle detected for promise #<Promise>
 // 处理重复引用
            const p2 = new MyPromise((resolve,reject)=>{
            if(this.status === FULFILLED){
               runAsyncTask(() => { 
                 try {
                   const x = onFulfilled(this.result)
                        // 判断是否重复
                    if(x===p2)
                    {
                        // 抛出异常Chaining cycle detected for promise #<Promise>
                        throw new TypeError('Chaining cycle detected for promise #<Promise>')
                    }
                   if(x instanceof MyPromise){
                       x.then(res => resolve(res),err => reject(err))
                   }
                   else{resolve(x)}
                 } catch (error) {
                    reject(error)
                 }
               })

成功捕获错误!

对于reject同理,同样需要处理返回值和异常、处理返回promise、获取重复调用四个步骤,用于代码需要重复调用,所以我们将其封装成函数以进行复用


        // 抽取函数
        function resolvePromise(p2,x,resolve,reject){
            if(x === p2){
                throw new TypeError('Chaining cycle detected for promise #<Promise>')
            }
            if(x instanceof MyPromise){
                x.then(res => resolve(res),err => reject(err))
            }else{
                resolve(x)
            }
        }

功能正常!

作为中立状态的pending也必不可少,同样需要处理返回值和异常、处理返回promise、获取重复调用四个步骤。

 // 添加回调函数
               this.#handlers.push({
                onFulfilled:()=>{
                    runAsyncTask(() => {
                        // 1、处理异常
                       try {
                        // 2、获取返回值
                        const x =  onFulfilled(this.result)
                        // 3、调用函数
                        resolvePromise(p2,x,resolve,reject)
                       } catch (error) {
                        reject(error)
                       }
                    })
                }
                ,
                onRejected:()=>{
                    runAsyncTask(() => {
                        // 1、处理异常
                        try {
                        // 获取返回值
                        const x = onRejected(this.result)
                        resolvePromise(p2,x,resolve,reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                }
            })

仍可成功获取。

实例方法:

.catch()

Promise 实例的 catch() 方法用于注册一个在 promise 被拒绝时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 的方法。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。

根据文档在then方法中添加已有catch方法,却发现无法调用reject中捕获异常功能,而是在调试throw error使用浏览器报错,故在自己定义的reject方法中使用try catch 捕获错误。

  const reject = (result) => {
                    if(this.status === PENDING){
                        // 修改状态并记录结果
                        this.status = REJECTED
                        this.result = result
                        // 调用失败回调函数
                        this.#handlers.forEach(({onRejected}) => {
                            onRejected(result)
                        })
                }
            }
                // 处理异常
                try {
                    func(resolve,reject)  
                } catch (error) {
                    reject(error)
                }
  then(onFulfilled,onRejected){
            // 根据mdn知道需要判断回调函数是否为函数,如果不是需要处理
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
            onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
            // 处理重复引用
            const p2 = new MyPromise((resolve,reject)=>{
            if(this.status === FULFILLED){
               runAsyncTask(() => { 
                 try {
                   const x = onFulfilled(this.result)
                   resolvePromise(p2,x,resolve,reject)
                //         // 判断是否重复
                //     if(x===p2)
                //     {
                //         // 抛出异常Chaining cycle detected for promise #<Promise>
                //         throw new TypeError('Chaining cycle detected for promise #<Promise>')
                //     }
                //    if(x instanceof MyPromise){
                //        x.then(res => resolve(res),err => reject(err))
                //    }
                //    else{resolve(x)}
                 } catch (error) {
                    reject(error)
                 }
               })
            }
            else if(this.status === REJECTED){
                runAsyncTask(() => {
                    try {
                        const x = onRejected(this.result)
                        resolvePromise(p2,x,resolve,reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }//异步和多次调用
            else if(this.status === PENDING){
                // 添加回调函数
               this.#handlers.push({
                onFulfilled:()=>{
                    runAsyncTask(() => {
                        // 1、处理异常
                       try {
                        // 2、获取返回值
                        const x =  onFulfilled(this.result)
                        // 3、调用函数
                        resolvePromise(p2,x,resolve,reject)
                       } catch (error) {
                        reject(error)
                       }
                    })
                }
                ,
                onRejected:()=>{
                    runAsyncTask(() => {
                        // 1、处理异常
                        try {
                        // 获取返回值
                        const x = onRejected(this.result)
                        resolvePromise(p2,x,resolve,reject)
                        } catch (error) {
                            reject(error)
                        }
                      })
                    }
                  })
               }
            })
           return p2
        }
        
            catch(onRejected){
                return this.then(undefined,onRejected)
            }
        }
// 测试手写
        const p = new MyPromise((resolve,reject) => {
           // reject('fail')
            throw 'error!'
        })
        p.then(res=>{
            console.log('res:',res)
        }).catch(err => {
            console.log('err:',err)
        })

.finally

Promise 实例的 finally() 方法用于注册一个在 promise 敲定(兑现或拒绝)时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 方法。

无论错误还是成功都不会影响调用.finally时的输出。

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

静态方法:

.resolve()

Promise.resolve() 静态方法将给定的值转换为一个 Promise。如果该值本身就是一个 Promise,那么该 Promise 将被返回;如果该值是一个 thenable 对象,Promise.resolve() 将调用其 then() 方法及其两个回调函数;否则,返回的 Promise 将会以该值兑现。

 // 添加静态方法
            static resolve(value){
                if(value instanceof MyPromise){
                    return value
                }
                return new MyPromise((resolve,reject) => {
                    resolve(value)
                })
            }
      
 // 测试手写
        MyPromise.resolve(new MyPromise((resolve,reject) => {
            //resolve(1)
            //reject('fail')
            //throw 'error'
        })).then(res => {
            console.log('res:',res)
        },err=>{
            console.log('err:',err)
        })

        MyPromise.resolve('ian').then(res=>{
            console.log('res:',res)
        })

.reject()

Promise.reject() 静态方法返回一个已拒绝(rejected)的 Promise 对象,拒绝原因为给定的参数。

static reject(value){
                return new MyPromise((undefined,reject) => {
                    reject(value)
                })
            }
.race()

Promise.race() 静态方法接受一个 promise 可迭代对象作为输入,并返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。

static race(promises){
               // 1、返回Promise对象
                return new MyPromise((resolve,reject)=>{
                    // 2、判断是否为数组
                    if(!Array.isArray(promises)){
                       return reject(new TypeError('You must pass an array')) 
                    }
                    // 3、等待第一个敲定
                    promises.forEach(p=>{
                        //p.then
                        MyPromise.resolve(p).then(res => {resolve(res)},err => {reject(err)})
                    })
                }) 
            }
.all()

Promise.all() 静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。

static all(promises){
                // 1、返回Promise对象
                return new MyPromise((resolve,reject)=>{
                    // 2、判断是否为数组
                    if(!Array.isArray(promises)){
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 3、空数组直接兑现
                    promises.length === 0 && resolve(promises)
                    // 4、处理全部兑现
                    //     4.1、记录结果:使用索引来记录,保证结果的顺序和Promise数组的顺序一致
                    //     4.2、判断是否全部兑现:通过兑现的次数来判断,保证可以获取道德所有结果
                    const results = [] // 记录结果
                    let count = 0 // 记录兑现次数
                    promises.forEach((p,index)=>{
                        MyPromise.resolve(p).then(
                            res => {
                                results[index] = res
                                // 判断是否全部兑现
                                count++
                                count === promises.length && resolve(results)
                            },
                            err => {
                                // 有一个失败则全部失败
                                reject(err)
                            }
                        )
                    })
                })
            }

.allSettled()

Promise.allSettled() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise。当所有输入的 Promise 都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组。

无论是resolve还是reject都属于promise的pending敲定,使用resolve!
 

  static allSettled(promises){
                // 1、返回Promise对象
                return new MyPromise((resolve,reject)=>{
                    // 2、判断是否为数组
                    if(!Array.isArray(promises)){
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 3、空数组直接兑现
                    promises.length === 0 && resolve(promises)
                    // 4、处理全部兑现
                    //     4.1、记录结果:使用索引来记录,保证结果的顺序和Promise数组的顺序一致
                    const results = [] // 记录结果
                    let count = 0 // 记录兑现次数
                    promises.forEach((p,index)=> {
                        MyPromise.resolve(p).then(
                         res =>{
                            // 4.2、处理兑现{status: FULFILLED,value: res}
                            results[index] = {status: FULFILLED,value: res}
                            count++
                            count === promises.length && resolve(results)
                         },err=>{
                            // 4.3、处理拒绝{status: REJECTED,reason: err}
                            results[index] = {status: REJECTED,reason: err}
                            count++
                            count === promises.length && resolve(results)
                         }
                        )
                    })
                })
            }
// 测试手写
        const p1 = MyPromise.resolve(1)
        const p2 = 2
        const p3 = new MyPromise((resolve,reject) => {
            setTimeout(() => {
               // resolve(3)
                reject('fail')
            },1000)
        })
        MyPromise.allSettled([p1,p2,p3]).then(res => {
            console.log('res:',res)
        },err => {
            console.log('err:',err)
        })

.any()

Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。

AggregateError 对象代表了包装了多个错误对象的单个错误对象。当一个操作需要报告多个错误时,例如 Promise.any(),当传递给它的所有承诺都被拒绝时,就会抛出该错误。

AggregateError 是 Error 的子类。

            static any(promises){
                // 1、返回Promise对象
                return new MyPromise((resolve,reject)=>{
                    // 2、判断是否为数组
                    if(!Array.isArray(promises)){
                        return reject(new TypeError('Argument is not iterable'))
                    }
                    // 3、空数组直接拒绝
                    promises.length === 0 && reject(new AggregateError(promises,'All promises were rejected'))
                    // 4、处理第一个兑现
                    //     4.1、记录结果:使用索引来记录,保证结果的顺序和Promise数组的顺序一致
                    //     4.2、判断是否全部兑现:通过兑现的次数来判断,保证可以获取道德所有结果
                    const errors = [] // 记录结果
                    let count = 0 // 记录兑现次数
                    promises.forEach((p,index)=>{
                        MyPromise.resolve(p).then(
                            // 第一个兑现
                            res => {
                                resolve(res)
                            },
                            err => {
                                // 全部拒绝
                                errors[index] = err
                                count++
                                count === promises.length && reject(new AggregateError(errors,'All promises were rejected'))
                            }
                        )
                    })
                })
            }
 // 测试手写
        const p1 = new MyPromise((resolve,reject) => {
            setTimeout(() => {
                //resolve(1)
                reject(1)
            },2000)
        })
        const p2 = MyPromise.reject(2)
        const p3 = new MyPromise((resolve,reject) => {
            setTimeout(() => {
                //resolve(3)
                reject(3)
            },1000)
        })
       // MyPromise.any([]).then(res => {
        //MyPromise.any().then(res => {
        MyPromise.any([p1,p2,p3]).then(res => {
            console.log('res:',res)
        },err => {
            console.dir(err)
        })

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

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

相关文章

基于SpringBoot+Vue光影视频平台(源码+部署说明+演示视频+源码介绍)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

ChernoCPP 2

视频链接&#xff1a;【62】【Cherno C】【中字】C的线程_哔哩哔哩_bilibili 参考文章&#xff1a;TheChernoCppTutorial_the cherno-CSDN博客 Cherno的C教学视频笔记&#xff08;已完结&#xff09; - 知乎 (zhihu.com) C 的线程 #include<iostream> #include<th…

SV学习笔记(六)

覆盖率类型 写在前面 覆盖率是 衡量设计验证完备性 的一个通用词。随着测试逐步覆盖各种合理的场景&#xff0c;仿真过程会慢慢勾画出你的设计情况。覆盖率工具会 在仿真过程中收集信息 &#xff0c;然后进行后续处理并且得到覆盖率报告。通过这个报告找出覆盖之外的盲区&…

设计模式——原型模式05

原型模式核心复制&#xff0c;每次new出来的对象完全不一样&#xff0c;实现对象之间的隔离。 学习前最好先掌握jAVA值传递和深浅拷贝 设计模式&#xff0c;一定要敲代码理解 浅拷贝 克隆出对象&#xff0c;其中两者的引用类型属性是同一个对象。 对象信息 /*** author ggb…

C++:逻辑运算符-非与或(19)

!非!a如果a为假&#xff0c;那么当前他就是真&#xff0c;如果a是真&#xff0c;那么他直接就是假&&与a&&ba与b都为真&#xff0c;那么就是真&#xff0c;如果两个里面有一个为假那么就是假||或a||ba或b有一个为真&#xff0c;那么就是真 非&#xff08;!&…

怎样把学浪购买的课程下载下来

如何把学浪已购买的课程下载下来?这里就教大家一个方法,利用一个工具轻轻松松把视频下载下来 这个工具我打包成压缩包了,有需要的自己取一下 链接&#xff1a;https://pan.baidu.com/s/1y7vcqILToULrYApxfEzj_Q?pwdkqvj 提取码&#xff1a;kqvj --来自百度网盘超级会员V1…

基于springboot+vue+Mysql的在线考试系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

redis集合Set

set是一种无序集合。它和列表的区别在于列表中的元素都是可以重复的&#xff0c;而set中的元素是不能重复的。而且set中的元素&#xff0c;并不像列表那样是具有顺序的。 SADD是添加一个元素。course是集合。 SMEMBERS SISMEMBER判断Redis在不在集合course里 SREM是用来删除Re…

Jupyter Notebook安装使用(一)

1. 简介 Jupyter Notebook 是一个非常强大的工具&#xff0c;它允许用户创建和共享包含实时代码、方程式、可视化和叙事文本的文档。这种工具特别适合数据清理和转换、数值模拟、统计建模、数据可视化、机器学习等多种应用领域。 2. 安装Jupyter Notebook 2.1. 使用 Anaconda…

校招说明书

3400字的详细说明&#xff0c;介绍了程序员类岗位校招的整体时间节点和招聘流程。还对一些常见的问题进行讨论&#xff0c;例如内推、offer和三方、实习等。 第一章介绍基本的术语&#xff0c;第二章介绍整个校招的重要流程及时间点&#xff0c;然后第三章介绍每次招聘要经过的…

golang 和java对比的优劣势

Golang&#xff08;或称Go&#xff09;和Java都是非常流行的编程语言&#xff0c;被广泛应用于各种领域的软件开发。尽管它们都是高级编程语言&#xff0c;但它们具有许多不同的特性和适用场景。本文将重点比较Golang和Java&#xff0c;探讨它们的优势和劣势。 性能方面&#…

JSP

文章目录 JSP1. 快速入门2. page 指令3. 三种常用脚本声明脚本表达式脚本代码脚本 4. 注释5. 内置对象6. 域对象7. 请求转发标签8. EL 表达式快速入门EL运算操作EL的11个隐含对象四个特定域变量 9. JSTL快速入门<c:set /><c:if />\<c:choose> \<c:when>…

【微服务】------核心组件架构选型

1.微服务简介 微服务架构&#xff08;Microservice Architecture&#xff09;是一种架构概念&#xff0c;旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦&#xff0c;从而降低系统的耦合性&#xff0c;并提供更加灵活的服务支持。 2.微服务技术选型 区域内容…

爬虫学习第一天

爬虫-1 爬虫学习第一天1、什么是爬虫2、爬虫的工作原理3、爬虫核心4、爬虫的合法性5、爬虫框架6、爬虫的挑战7、难点8、反爬手段8.1、Robots协议8.2、检查 User-Agent8.3、ip限制8.4、SESSION访问限制8.5、验证码8.6、数据动态加载8.7、数据加密-使用加密算法 9、用python学习爬…

汽车疲劳测试试验平台技术要求(北重厂家)

汽车疲劳测试试验平台技术要求通常包括以下几个方面&#xff1a; 车辆加载能力&#xff1a;测试平台需要具备足够的承载能力&#xff0c;能够同时测试多种车型和不同重量的车辆。 动力系统&#xff1a;测试平台需要具备稳定可靠的动力系统&#xff0c;能够提供足够的力和速度来…

C++ 指针与数组

指针与数组名都是地址&#xff0c;可以混合使用访问数组元素。 用指针访问数组&#xff0c;计算数组元素之和。 总结 如图所示&#xff0c;获取数组起始地址的方法有两种&#xff0c; 其一为数组名&#xff0c; 其二为通过数组的首元素地址。指针变量p是通过数组名获得指向…

通用开发技能系列:SQL基础学习

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 通用开发技能系列 文章&#xff0c;主要对编程通用技能 SQL基础 进行学习 1.数据库简介 1.1.数据库中的一些名称 DataBase&#xff1a;数据库 程序员只负责怎么维护存取数据&#xff0c;不管数据库是什么 DBA…

Deep Unsupervised Learning using Nonequilibrium Thermodynamics

就直接从算法部分开始了&#xff1a; 2 算法 我们的目标是定义一个前向&#xff08;或者推理&#xff09;扩散过程&#xff0c;这个过程能够转换任意的复杂数据分部到一个简单、tractable、分布&#xff0c;并且学习有限时间扩散过程的反转 从而 定义我们的生成模型分布。我们…

“人性化设计”技术概要

本文是由《埃森哲技术愿景 2024&#xff1a;“人性化设计”技术将通过提高生产力和创造力来重塑行业并重新定义领导者》这个文章来翻译解读的。原文地址如下&#xff0c;大家可以自行下载&#xff1a; 下载地址 其实看到这篇文章的时候&#xff0c;联想到这些年机器人的市场发展…

使用 HTMX 和 Bun 进行全栈 Web 开发

将 HTMX 放在前端&#xff0c;Bun 放在后端&#xff0c;然后将它们与 Elysia 和 MongoDB 连接起来&#xff0c;形成快速便捷的技术栈&#xff0c;使开发 Web 应用程序变得轻而易举。 Bun 和 HTMX 是目前软件领域最有趣的两个事情。 Bun 是一个速度极快的一体化服务器端 JavaSc…