JS详解-手写Promise!!!

前言:

针对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 = PENDINGresult = undefined// 添加构造函数constructor(func){// 定义resolve和reject方法const resolve = (value) => {// 修改状态并记录原因this.status = FULFILLEDthis.result = value}const reject = (value) => {// 修改状态并记录原因this.status = REJECTEDthis.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 = FULFILLEDthis.result = result}}const reject = (result) => {if(this.status === PENDING){// 修改状态并记录结果this.status = REJECTEDthis.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 = FULFILLEDthis.result = result}}const reject = (result) => {if(this.status === PENDING){// 修改状态并记录结果this.status = REJECTEDthis.result = result}}// 初始化状态func(resolve,reject)}then(onFulfilled,onRejected){// 根据mdn知道需要判断回调函数是否为函数,如果不是需要处理onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => valueonRejected = 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 = FULFILLEDthis.result = result// 调用成功回调函数this.#handlers.forEach(({onFulfilled}) => {onFulfilled(result)})}}const reject = (result) => {if(this.status === PENDING){// 修改状态并记录结果this.status = REJECTEDthis.result = result// 调用失败回调函数this.#handlers.forEach(({onRejected}) => {onRejected(result)})}}// 初始化状态func(resolve,reject)}then(onFulfilled,onRejected){// 根据mdn知道需要判断回调函数是否为函数,如果不是需要处理onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => valueonRejected = 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:
   // 异步任务 queueMicrotaskconsole.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、修改元素内容,观察器触发MutationObserverdivNode.innerText = 'hello'
函数封装:
// 封装函数分别使用queueMicrotask和MutationObserver setTimeout实现异步任务function runAsyncTask(callback){// 使用queueMicrotaskif(typeof queueMicrotask === 'function'){queueMicrotask(callback)}else if (typeof MutationObserver === 'function'){// 使用MutationObserverconst 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 => valueonRejected = 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 = REJECTEDthis.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 => valueonRejected = 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.thenMyPromise.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 = 2const 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] = errcount++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.hqwc.cn/news/593425.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python-基础篇-字符串、列表、元祖、字典-字符串

文章目录 2.3字符串、列表、元祖、字典2.3.1字符串2.3.1.1字符串介绍2.3.1.1.1python中字符串的格式&#xff1a;2.3.1.1.2字符串在内存中的存储方式 2.3.1.2字符串的输入输出2.3.1.2.1字符串输出2.3.1.2.2字符串输入2.3.1.2.3组字符串的方式 2.3.1.3下标和切片2.3.1.3.1下标索…

挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题

前言 大概故事是这样的&#xff0c;PostgreSQL数据库&#xff0c;表结构&#xff1a; create table t1(a varchar);然后使用标准的Java jdbc去插入数据&#xff0c;其基本代码如下&#xff1a; import java.sql.*; public class PgDoubleTest {public static void main(Stri…

聊聊测试用例评审流程

测试人员将需求熟悉完成后&#xff0c;开始编写相应的测试用例&#xff0c;待测试用例编写完成后只是测试用例完成前的第一步&#xff0c;后边的流程需要组织线上或线下评审会议等等。 首先要了解测试用例评审的最终目的是什么&#xff1a;提高测试用例的质量和覆盖率&#xff…

学浪里面的视频怎么保存到本地

很多人都在学浪里面买了课程,可是却找不到下载学浪课程的方法&#xff0c;这里Leo小黑教大家如何把学浪里购买的视频课程下载下来 注意:此方法不可以下载直播回放 1.解压我给大家准备的小浪助手.exe 2.打开小浪助手.exe 3.要是有抖音账号和学浪绑定的手机账号一样那就可以直接…

3.6k star, 免费开源跨平台的数据库管理工具 dbgate

3.6k star, 免费开源跨平台的数据库管理工具 dbgate 分类 开源分享 项目名: dbgate -- 免费开源跨平台的数据库管理工具 Github 开源地址&#xff1a; GitHub - dbgate/dbgate: Database manager for MySQL, PostgreSQL, SQL Server, MongoDB, SQLite and others. Runs under…

Python如何解决“滑动拼图”验证码(8)

前言 本文是该专栏的第67篇,后面会持续分享python爬虫干货知识,记得关注。 做过爬虫项目的同学,或多或少都会接触到一些需要解决验证码才能正常获取数据的平台。 在本专栏之前的文章中,笔者有详细介绍通过python来解决多种“验证码”(点选验证,图文验证,滑块验证,滑块…

【Java笔记】多线程0:JVM线程是用户态还是内核态?Java 线程与OS线程的联系

文章目录 JVM线程是用户态线程还是内核态线程什么是用户态线程与内核态线程绿色线程绿色线程的缺点 线程映射稍微回顾下线程映射模型JVM线程映射 线程状态操作系统的线程状态JVM的线程状态JVM线程与OS线程的状态关系 Reference 今天复盘一下Java中&#xff0c;JVM线程与实际操作…

全流程基于GIS、python机器学习技术的地质灾害风险评价与信息化建库应用

入门篇&#xff0c;ArcGIS软件的快速入门与GIS数据源的获取与理解&#xff1b;方法篇&#xff0c;致灾因子提取方法、灾害危险性因子分析指标体系的建立方法和灾害危险性评价模型构建方法&#xff1b;拓展篇&#xff0c;GIS在灾害重建中的应用方法&#xff1b;高阶篇&#xff1…

(三)LTspice学习交流分析

文章目录 前言一、Edit simulation cmd二、添加激励总结 前言 上一节我们学习了LTspice的安装&#xff0c;很简单&#xff0c;无脑安装 &#xff08;一&#xff09;LTspice简介 &#xff08;二&#xff09;LTspice学习之简介2 今天我们来学习一下LTspice另一个非常重要的仿真功…

改进YOLO:YOLOv8结合swin transformer

目录 1、修改yaml文件 2、添加 SwinTransformer.py 3、修改 tasks.py 4、根目录增加文件 1、修改yaml文件 修改 ultralytics/cfg/models/v8/yolov8.yaml backbone:# [from, repeats, module, args]- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2- [-1, 1, Conv, [128, 3, 2]] #…

node.js的模块化 与 CommonJS规范

一、node.js的模块化 (1)什么是模块化&#xff1f; 将一个复杂的程序文件依据一定的规则拆分成为多个文件的过程就是模块化 在node.js中&#xff0c;模块化是指把一个大文件拆分成独立并且相互依赖的多个小模块&#xff0c;将每个js文件被认为单独的一个模块&#xff1b;模块…

【C++】vector问题解决(非法的间接寻址,迭代器失效 , memcpy拷贝问题)

送给大家一句话&#xff1a; 世界在旋转&#xff0c;我们跌跌撞撞前进&#xff0c;这就够了 —— 阿贝尔 加缪 vector问题解决 1 前言2 迭代器区间拷贝3 迭代器失效问题4 memcpy拷贝问题 1 前言 我们之前实现了手搓vector&#xff0c;但是当时依然有些问题没有解决&#xff…