从如何使用到如何实现一个Promise

promise是什么?主要用来解决什么问题?

Promise是异步编程的一种解决方案,比传统解决方案--回调函数和事件--更合理更强大。

Promise特点:

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中),fulfilled(已成功)和reject(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其它操作都无法改变这个状态。这也是Promise(承诺)这个名字的由来。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected

promise主要用来解决:

  • 回调地狱

  • 并发请求

  • 异步方案优化(但它本身不是异步的,new Promise()后,它会立即执行)

promise基本用法

ES6规定,Promise对象是一个构造函数,用来生成Promise实例

下面代码创造了一个Promise实例

const promise = new Promise(function(resolve,reject){
    //...
    if(/*异步操作成功*/){
       resolve(value)
    }else{
        //异步操作失败
        reject(error)
    }
})

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject.他们是两个函数,由JavaScript引擎提供,不用自己部署。

resolve函数的作用是,将Promise对象的状态从“未完成”变成“成功”(即从pending变为resolve),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变成“失败”(即从pending变为rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数,或用catch方法指定rejected状态的回调函数。

promise.then(res=>{
    //success
},error=>{
    //error
}).catch(err=>{})

then方法可以接受两个回调函数作为参数,第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接收Promise对象传出的值作为参数。

「Ok,通过上面对promise基本用法的描述,我们大概知道了一个promise类里面都应该包含哪些内容了:」

  • promise状态:pending,fulfilled,rejected

  • promise返回值

  • 执行器:promise执行入口(也就是你传入的那个函数)

  • resolve:改变promise状态为fulfilled

  • reject:改变promise状态为rejected

  • then:接收两个回调,onFulfilled, onRejected。分别在promise状态变为fulfiled或rejected后执行

  • catch:接受一个回调,在promise状态变为rejected后执行

简单实现一个promise

我们知道了一个promise内容至少包含以上那些内容,所以一个简单的promise内部至少是这样的

class myPromise {
    static PENDING = 'pending'
    static FULFILLEd = 'fulfilled'
    static REJECTED = 'rejected'
    constructor(init){
        this.state = myPromise.PENDING // promise状态
        this.promiseRes = null  // promise返回值
        const resolve = result=>{
        //...
        }
        const reject = result=>{
           //...
        }
        try{
            init(resolve,reject)  // init就是初始化执行器
        }catch(err){
            reject(err)
        }
        
    }
    then(onFulfilled,onRejected){
       //...
    }
   catch(onRejected){
      //...
    }
}

OK,大概了解之后,我们再来一个一个的看里面每个部分的实现以及作用

Promise的执行器

它其实是我们在new Promise时传入的一个回调函数,这个函数本身是同步的,也就是说在new Promise时它就会执行,这也是我们操作promise的入口。

class myPromise{
  //...
  constructor(init){
        try{
            init(resolve,reject)  // init就是初始化执行器
        }catch(err){
            reject(err) //这里主要是在init执行器函数出错时,用以让promise状态变为rejected
        } 
    }
  //...
}

该函数接受两个回调函数(resolve,reject)作为参数,用以改变Promise的状态

resolve与reject方法

这两个函数作为参数传到执行器函数中,用以后续改变Promise状态

class myPromise {
    static PENDING = 'pending'
    static FULFILLEd = 'fulfilled'
    static REJECTED = 'rejected'
    constructor(init){
        this.state = myPromise.PENDING // promise状态
        this.promiseRes = null  // promise返回值
        this.resolveCallback = [] //成功回调集合
        this.rejectCallback = [] //失败回调集合
        const resolve = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.FULFILLEd //改变状态
                this.promiseRes = result //返回值
                //依次调用成功回调
                this.resolveCallback.forEach(fn=>fn())
            }
        }
        const reject = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.REJECTED //改变状态
                this.promiseRes = result //返回值
                // 依次调用失败回调
                this.rejectCallback.forEach(fn=>fn())
            }
        }
        try{
            init(resolve,reject)  // 注意this指向
        }catch(err){
            reject(err)
        }
        
    }
}

初步then方法

class myPromise {
    static PENDING = 'pending'
    static FULFILLEd = 'fulfilled'
    static REJECTED = 'rejected'
    constructor(init){
        this.state = myPromise.PENDING // promise状态
        this.promiseRes = null  // promise返回值
        this.resolveCallback = [] //成功回调集合
        this.rejectCallback = [] //失败回调集合
        const resolve = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.FULFILLEd //改变状态
                this.promiseRes = result //返回值
                //依次调用成功回调
                this.resolveCallback.forEach(fn=>fn())
            }
        }
        const reject = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.REJECTED //改变状态
                this.promiseRes = result //返回值
                // 依次调用失败回调
                this.rejectCallback.forEach(fn=>fn())
            }
        }
        try{
            init(resolve,reject)  // 注意this指向
        }catch(err){
            reject(err)
        }
        
    }
    then(onFulfilled,onRejected){
        if(this.state === myPromise.FULFILLEd && typeof onFulfilled === 'function') {
            onFulfilled(this.promiseRes)
        }
        if(this.state === myPromise.REJECTED && typeof onRejected === 'function') {
            onRejected(this.promiseRes)
        }
    }
}

写到这里,我们的promise已经初步成型了,我们可以来测试一下:

const res1 = new myPromise((res,rej)=>{
    res('成功啦~')
    rej('失败啦~')
})
res1.then((res)=>{
    console.log(res)
},err=>{
    console.log(err)
})
// 按照预期,这里应该是只会打印出成功啦~

从上图看我们,是不是符合我们的预期,并且myPromise内部与原生的Promise也是非常相似的。你们是不是觉得这里已经没问题了,上面我们只是测了一下同步方法的执行,但别忘了,Promise主要是来解决异步问题的,我们再来试一下里面执行异步方法还符不符合我们的预期?

const res1 = new myPromise((res,rej)=>{
    setTimeout(()=>res('成功啦~'),1000)
    // rej('失败啦~')
})
res1.then((res)=>{
    console.log(res)
})

这里我们预期本来是一秒之后打印成功啦,但它并没有如我们所愿,反而是什么也没打印出来,这是因为在setTimeout执行之前(pending)这个then方法已经执行过了,1s后状态变成fulfilled时,then也不会再执行了。

「所以我们需要保证then方法的回调函数在promise状态变成fulfilledrejected时再执行,那么当promise状态为pending时我们先要把回调存在对应的队列中,等后续状态改变后再执行」

较完整then方法

OK,这里我们修改一下我们的then方法,让其保证异步代码执行的正确性 (具体实现微任务我们可以用 mutationObserver,这里我们就用setTimeout来模拟一下)

class myPromise {
    static PENDING = 'pending'
    static FULFILLEd = 'fulfilled'
    static REJECTED = 'rejected'
    constructor(init){
        this.state = myPromise.PENDING // promise状态
        this.promiseRes = null  // promise返回值
        this.resolveCallback = [] //成功回调集合
        this.rejectCallback = [] //失败回调集合
        const resolve = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.FULFILLEd //改变状态
                this.promiseRes = result //返回值
                //依次调用成功回调
                this.resolveCallback.forEach(fn=>fn())
            }
        }
        const reject = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.REJECTED //改变状态
                this.promiseRes = result //返回值
                // 依次调用失败回调
                this.rejectCallback.forEach(fn=>fn())
            }
        }
        try{
            init(resolve,reject)  // 注意this指向
        }catch(err){
            reject(err)
        }
        
    }
    then(onFulfilled,onRejected){
        if(this.state === myPromise.FULFILLEd && typeof onFulfilled === 'function') {
            onFulfilled(this.promiseRes)
        }
        if(this.state === myPromise.REJECTED && typeof onRejected === 'function') {
            onRejected(this.promiseRes)
        }
        if(this.state === myPromise.PENDING){
            if(onFulfilled && typeof onFulfilled === 'function'){
                this.resolveCallback.push(()=>
                // 这里我们用setTimeout来模拟实现then的微任务
                setTimeout(()=>{
                    onFulfilled(this.promiseRes)
                },0)
                )
            }
            if(onRejected && typeof onRejected === 'function'){
                this.rejectCallback.push(()=>
                // 这里我们用setTimeout来模拟实现then的微任务
                setTimeout(()=>{
                    onRejected(this.promiseRes)
                },0)
                )
            }
        }
    }
}

这里我们可以再测试一下上面那个异步函数的测试用例,发现它能够正确打印,OK,一个较完整的then方法就算实现了~

then的链式调用

then方法会返回一个新的Promise(⚠️注意:不是原来的那个Promise)所以可以采用链式调用

采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。

then(onFulfilled,onRejected){
        const {promiseRes,state} = this
        let promise = new myPromise((reso,reje)=>{
            const resolveMyPromise = promiseRes => {
                try{
                    if(typeof onFulfilled !== 'function'){
                        // 如果then的第一个回调不是一个函数,直接忽略,返回一个新的promise
                        reso(promiseRes)
                    }else{
                        // 获取第一个回调的执行结果
                        const res = onFulfilled(promiseRes)
                        // 看该执行结果是否是一个promise
                        if(res instanceof myPromise){
                            // 是一个promise,等它状态改变后再改变then返回的promise状态
                            res.then(reso,rej) 
                        }else{
                            // 不是一个promise,将它作为新的promise的resolve
                            reso(res)
                        }
                    }
                }catch(err){
                    //异常,直接将新的promise状态置为rejected
                    reje(err)
                }
            }
            const rejectMyPromise = promiseRes => {
                try{
                    if(typeof onRejected !== 'function'){
                        // 如果then的第二个回调不是一个函数,直接忽略,返回一个新的promise
                        reje(promiseRes)
                    }else{
                        // 获取第二个回调的执行结果
                        const res = onRejected(promiseRes)
                        // 看该执行结果是否是一个promise
                        if(res instanceof myPromise){
                            // 是一个promise,等它状态改变后再改变then返回的promise状态
                            res.then(reso,rej) 
                        }else{
                            // 不是一个promise,将它作为新的promise的resolve
                            reje(res)
                        }
                    }
                    
                }catch(err){
                    //异常,直接将新的promise状态置为rejected
                    reje(err)
                }
            }
            if(state === myPromise.FULFILLEd) {
                resolveMyPromise(promiseRes)
            }
            if(state === myPromise.REJECTED) {
                rejectMyPromise(promiseRes)
            }
            if(state === myPromise.PENDING){
                if(onFulfilled && typeof onFulfilled === 'function'){
                    this.resolveCallback.push(()=>
                    // 这里我们用setTimeout来模拟实现then的微任务
                    setTimeout(()=>{
                        resolveMyPromise(this.promiseRes)
                    },0)
                    )
                }
                if(onRejected && typeof onRejected === 'function'){
                    this.rejectCallback.push(()=>
                    // 这里我们用setTimeout来模拟实现then的微任务
                    setTimeout(()=>{
                        rejectMyPromise(this.promiseRes)
                    },0)
                    )
                }
            }

        })
        return promise
    }

catch方法

我们知道then的第二个回调其实与catch方法是一样的,所以catch方法我们可以这样实现

catch(onRejected) {
        return this.then(undefined,onRejected)
    }

Promise.resolve

将对象转为一个promise对象,根据参数不通可分为四种情况

  • 参数是一个Promise实例,直接返回该实例

  • 参数是一个thenable对象,将该对象转为Promise对象后,执行该对象的then方法

  • 没有参数,也是返回一个状态为resolved的新的Promise对象

  • 参数是一个一个原始值,返回一个新的Promise对象,状态为resolved

static resolve(v){
  //1.参数是一个Promise实例,直接返回
  if(v instanceof myPromise){
    return v
  }
  //2.参数是一个thenable对象,转为Promise后执行该对象的then方法
  if(typeof v === 'object' && typeof v.then === 'function'){
    return new myPromise((res,rej)=>{
      v.then(res,rej)
    })
  }
  //3.没有参数,直接返回一个resolved状态的promise
  if(!v){
    return new myPromise(res=>{
      res()
    })
  }
  //4.参数是一个原始值,返回一个新的Promise,状态为resolved
  return new myPromise(res=>{
    res(v)
  })
}

Promise.reject

返回一个新的Promise对象,状态为rejected

static reject(v){
  return new myPromise((res,rej)=>{
    rej(v)
  })
}

Promise.all

该方法用于将多个Promise实例包装成一个新的Promise实例,如果有不是Promise的项,则让该项直接成功

const p = Promise.all([p1,p2,p3])

p的状态由p1p2p3决定,分成两种情况。

(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Ok,了解完Promise.all我们动手来实现一遍

static all (promises){
        return new myPromise((res,rej)=>{
            let count = 0
            const result = [];
            function addFun(index,resf) {
                result[index]=resf // 这里用索引别用push,保证返回的顺序
                count++
                if(count==promises.length) {
                    res(result)
                }
            }
            [].forEach.call(promises,(promise,index)=>{
                if(promise instanceof myPromise) {
                    promise.then(success=>{
                        // count ++
                        // result.push(success)
                        addFun(index,success)
                    },err=>{
                        rej(err)
                    })
                }else{
                    addFun(index,promise)
                }
            })
        })
    }

Promise.race

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

static race(promises) {
        return new myPromise((res,rej)=>{
            [].forEach.call(promises,promise=>{
                if(promise instanceof myPromise){
                    promise.then(success=>{
                        res(success)
                    },error=>{
                        rej(error)
                    })
                }else{
                    res(promise)
                } 
            })
        })
    }

完整代码

class myPromise {
    static PENDING = 'pending'
    static FULFILLEd = 'fulfilled'
    static REJECTED = 'rejected'
    constructor(init){
        this.state = myPromise.PENDING // promise状态
        this.promiseRes = null  // promise返回值
        this.resolveCallback = [] //成功回调集合
        this.rejectCallback = [] //失败回调集合
        const resolve = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.FULFILLEd //改变状态
                this.promiseRes = result //返回值
                //依次调用成功回调
                this.resolveCallback.forEach(fn=>fn())
            }
        }
        const reject = result=>{
            // 只有当状态为pending时才改变,保证状态一旦改变就不会再变
            if(this.state === myPromise.PENDING){
                this.state = myPromise.REJECTED //改变状态
                this.promiseRes = result //返回值
                // 依次调用失败回调
                this.rejectCallback.forEach(fn=>fn())
            }
        }
        try{
            init(resolve,reject)  // 注意this指向
        }catch(err){
            reject(err)
        }
        
    }
    then(onFulfilled,onRejected){
        const {promiseRes,state} = this
        let promise = new myPromise((reso,reje)=>{
            const resolveMyPromise = promiseRes => {
                try{
                    if(typeof onFulfilled !== 'function'){
                        // 如果then的第一个回调不是一个函数,直接忽略,返回一个新的promise
                        reso(promiseRes)
                    }else{
                        // 获取第一个回调的执行结果
                        const res = onFulfilled(promiseRes)
                        // 看该执行结果是否是一个promise
                        if(res instanceof myPromise){
                            // 是一个promise,等它状态改变后再改变then返回的promise状态
                            res.then(reso,rej) 
                        }else{
                            // 不是一个promise,将它作为新的promise的resolve
                            reso(res)
                        }
                    }
                }catch(err){
                    //异常,直接将新的promise状态置为rejected
                    reje(err)
                }
            }
            const rejectMyPromise = promiseRes => {
                try{
                    if(typeof onRejected !== 'function'){
                        // 如果then的第二个回调不是一个函数,直接忽略,返回一个新的promise
                        reje(promiseRes)
                    }else{
                        // 获取第二个回调的执行结果
                        const res = onRejected(promiseRes)
                        // 看该执行结果是否是一个promise
                        if(res instanceof myPromise){
                            // 是一个promise,等它状态改变后再改变then返回的promise状态
                            res.then(reso,rej) 
                        }else{
                            // 不是一个promise,将它作为新的promise的resolve
                            reje(res)
                        }
                    }
                    
                }catch(err){
                    //异常,直接将新的promise状态置为rejected
                    reje(err)
                }
            }
            if(state === myPromise.FULFILLEd) {
                resolveMyPromise(promiseRes)
            }
            if(state === myPromise.REJECTED) {
                rejectMyPromise(promiseRes)
            }
            if(state === myPromise.PENDING){
                if(onFulfilled && typeof onFulfilled === 'function'){
                    this.resolveCallback.push(()=>
                    // 这里我们用setTimeout来模拟实现then的微任务
                    setTimeout(()=>{
                        resolveMyPromise(this.promiseRes)
                    },0)
                    )
                }
                if(onRejected && typeof onRejected === 'function'){
                    this.rejectCallback.push(()=>
                    // 这里我们用setTimeout来模拟实现then的微任务
                    setTimeout(()=>{
                        rejectMyPromise(this.promiseRes)
                    },0)
                    )
                }
            }

        })
        return promise
    }
    catch(onRejected) {
        return this.then(undefined,onRejected)
    }
    static all (promises){
        return new myPromise((res,rej)=>{
            let count = 0
            const result = [];
            function addFun(index,resf) {
                result[index]=resf // 这里用索引别用push,保证返回的顺序
                count++
                if(count==promises.length) {
                    res(result)
                }
            }
            [].forEach.call(promises,(promise,index)=>{
                if(promise instanceof myPromise) {
                    promise.then(success=>{
                        addFun(index,success)
                    },err=>{
                        rej(err)
                    })
                }else{
                    addFun(index,promise)
                }
            })
        })
    }
    static race(promises) {
        return new myPromise((res,rej)=>{
            [].forEach.call(promises,promise=>{
                if(promise instanceof myPromise){
                    promise.then(success=>{
                        res(success)
                    },error=>{
                        rej(error)
                    })
                }else{
                    res(promise)
                } 
            })
        })
    }
    static resolve(v){
        //1.参数是一个Promise实例,直接返回
        if(v instanceof myPromise){
            return v
        }
        //2.参数是一个thenable对象,转为Promise后执行该对象的then方法
        if(typeof v === 'object' && typeof v.then === 'function'){
            return new myPromise((res,rej)=>{
                v.then(res,rej)
            })
        }
        //3.没有参数,直接返回一个resolved状态的promise
        if(!v){
            return new myPromise(res=>{
                res()
            })
        }
        //4.参数是一个原始值,返回一个新的Promise,状态为resolved
        return new myPromise(res=>{
            res(v)
        })
    }
    static reject(v){
        return new myPromise((res,rej)=>{
            rej(v)
        })
    }
}

总结

OK,上面跟大家一起过了一遍Promise的用法以及自己动手实现了一遍Promise,想必看完这篇文章,大家对Promise会有一个更加清晰的认识。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ModuleNotFoundError: No module named ‘openai.error‘

ModuleNotFoundError: No module named ‘openai.error’ result self.fn(*self.args, **self.kwargs) File “H:\chatGPTWeb\chatgpt-on-wechat\channel\chat_channel.py”, line 168, in _handle reply self._generate_reply(context) File “H:\chatGPTWeb\chatgpt-on-wec…

2023_Spark_实验二十九:Flume配置KafkaSink

实验目的:掌握Flume采集数据发送到Kafka的方法 实验方法:通过配置Flume的KafkaSink采集数据到Kafka中 实验步骤: 一、明确日志采集方式 一般Flume采集日志source有两种方式: 1.Exec类型的Source 可以将命令产生的输出作为源&…

性能加速包: SpringBoot 2.7JDK 17,你敢尝一尝吗 | 京东物流技术团队

前言 众所周知,SpringBoot3.0迎来了全面支持JDK17的局面,且最低支持版本就是JDK17,这就意味着,Spring社区将完全抛弃JDK8,全面转战JDK17。作为JAVA开源生态里的扛把子,Spring可以说是整个JAVA生态的风向标…

(8)Linux Makefile | 依赖关系,依赖方法

💭前言: 本篇文章会着重讲解Linux中的自动化构建代码工具: make/makefile的介绍与使用。 在Linux下编译代码时,每次都会输入 gcc code.c -o code.exe在删除可执行程序时,每次都会输入 rm -rf code.exe这样非常的不方便,很麻烦,于是乎学习自动化构建代…

原来Python的协程有2种实现方式

什么是协程 在 Python 中,协程(Coroutine)是一种轻量级的并发编程方式,可以通过协作式多任务来实现高效的并发执行。协程是一种特殊的生成器函数,通过使用 yield 关键字来挂起函数的执行,并保存当前的执行…

《Effective C++》学习笔记 续

条款31:将文件间编译依存关系降至最低 请记住: 支持”编译依存性最小化“的一般构想是:相依于声明式,不要相依于定义式。基于此构想的两个手段是Handle class和Interface class程序库头文件应该以”完全且仅有声明式“的形式存在…

uniapp 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码: uCharts: 高性能跨平台图表库,支持H5、APP、小程序(微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序)、Vue、Taro等更多支持canvas的框架平台&#…

网络安全之Linux环境配置及Linux基础知识讲解<三>

目录 一.下载安装Vmware二.下载安装Kali三.Linux目录结构四.Linux文件属性五.文件目录管理六.vim编辑器 一.下载安装Vmware Vmware官网:https://www.vmware.com 二.下载安装Kali Kali包含数百种工具,可用于各种信息安全任务,例如渗透测试、…

(C++)将x减到0的最小操作数--滑动窗口

个人主页:Lei宝啊 愿所有美好如期而遇 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://le…

微机总线地址物理内存地址虚拟内存地址简介

硬件地址的相关概念 Raspberry Pi 发布适用于 ARM 外设的 BCM2835 数据表 地址映射 总线地址 物理地址 虚拟地址 页表和内存管理单元MMU 《 Linux内核设计与实现(第三版)》 树莓派博通BCM2835芯片手册 硬件地址的相关概念 总线地址 32位的操作系统 &…

【赠书活动】OpenCV4工业缺陷检测的六种方法

文章目录 前言机器视觉缺陷检测工业上常见缺陷检测方法延伸阅读推荐语 赠书活动 前言 随着工业制造的发展,对产品质量的要求越来越高。工业缺陷检测是确保产品质量的重要环节,而计算机视觉技术的应用能够有效提升工业缺陷检测的效率和精度。 OpenCV是一…

【机器学习】卷积神经网络(CNN)的特征数计算

文章目录 基本步骤示例图解过程 基本步骤 在卷积神经网络(CNN)中,计算最后的特征数通常涉及到以下步骤: 确定输入尺寸: 首先,你需要知道输入数据的尺寸。对于图像数据,这通常是 (batch_size, c…

1-完全理解以太坊智能合约

了解区块链 区块链技术的核心概念是分布式账本,它是许多参与者共享的特定类型的数据库。 这个特殊的数据库只是一个交易列表,记录着网络中发生的每笔交易。每个人都可以拥有自己的交易列表备份,再加上强有力的货币激励措施消除各方之间信任…

记录今日将C语言的Windows程序更改为python语言Windows程序,实现子窗口控制,类似微信程序框架最简单的原型

基本思路 为什么要选择python制作Windows应用程序,主要就是源代码直接展示,发现问题随时修改,同时可以不断增加新的功能方便。 由于C语言的Windows程序中结构类型在python中不能使用, 因此我们按照ctypes模块指导意见继承structu…

基于双目RGB图像和图像深度信息的三维室内场景建模matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 双目视觉原理 4.2 深度信息获取 4.3 表面重建 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .....................................…

STM32与Freertos入门(三)任务的创建、删除

1、串口配置 首先将串口进行配置,后续经常会应用,具体步骤点击:串口配置。 2、任务 创建一个任务,就是开辟一个空间、每个任务中都会有while(1)死循环。 2.1相关函数 动态创建:xTaskCreate…

ros2/ros 4轮2驱机器人xacro/urdf文件示例代码

这个实验中最重要的是&#xff1a;colcon build 之后要记得source install/setup.bash.否则修改的文件是不会更新的。知道了吧 <robot name"half" xmlns:xacro"http://wiki.ros.org/wiki/xacro"><xacro:property name"PI" value"3…

SL3041高耐压100V降压恒压芯片 24V降压5V 24V降压12V 12V降5V

SL3041宽电压100V恒压芯片 24V降压5V 24V降压12V SL3041是一款宽电压100V恒压芯片&#xff0c;具有高效率、高精度、高可靠性等优点&#xff0c;广泛应用于各种电源系统中。在本文中&#xff0c;我们将详细介绍SL3041的工作原理、应用场景以及如何使用它实现24V降压5V和24V降压…

无框架Java转go语言写http与tcp请求

项目地址 https://github.com/cmdch2017/http_tcpServer 项目结构 如何快速上手 http篇 1、controller包就相当于RestController&#xff0c;这里返回了一个Person对象&#xff0c;当你需要新建一个接口时&#xff0c;再新写一个func仿照下面的方法就行了 package control…

GaussDB数据库表创建行访问控制策略

目录 一、前言 二、GaussDB中的行访问控制 1、CREATE ROW LEVEL SECURITY POLICY语法 2、ALTER ROW LEVEL SECURITY POLICY语法 3、ROW LEVEL SECURITY策略与适配SQL语法关系 三、GaussDB中的行访问控制策略示例 1、实现GaussDB行访问控制的一般步骤 2、行访问控制策略…