前端宝典二十一:前端异步编程规范手写Promise、async、await

news2024/9/19 10:44:15

本文主要探讨前端异步编程的处理方式、处理场景,并且手写Promise的全家桶,介绍async、await方法使用

一、异步处理方式有:

1. 回调函数

function fetchDate(callback) {
    setTimeout(() => {
        const date = new Date();
        callback(date);
    }, 1000);   
}
fetchDate((function(date) {
    console.log
}));

2. promise

const fetchPromise = (callback) => {
    return new Promise((resolve, reject) => {
        resolve(callback);
        reject('Error');
    }).then((date) => {
        console.log(date);
    }).catch((err) => {
        console.log(err);
    })
}

3. async、await

async function name(params) {
    try {
        const data1 = await fecth('https://jsonplaceholder.typicode.com/posts');
        const data2 = await fecth('https://jsonplaceholder.typicode.com/users');
        const data3 = await fecth('https://jsonplaceholder.typicode.com/comments');
    } catch (error) {
        console.log(error);
    }
}

4. 发布订阅模式

这里手写一个EventEmitter使用发布订阅模式实现异步操作:

class EventEmitter {
  constructor() {
    this.events = {};
  }

  on(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  emit(eventName,...args) {
    if (this.events[eventName]) {
      this.events[eventName].forEach(callback => callback(...args));
    }
  }

  off(eventName, callback) {
    if (this.events[eventName]) {
      this.events[eventName] = this.events[eventName].filter(cb => cb!== callback);
    }
  }
}

const eventEmitter = new EventEmitter();

function asyncOperation() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Async operation completed!');
    }, 2000);
  });
}

async function performAsyncWithPubSub() {
  eventEmitter.on('operationCompleted', result => {
    console.log(result);
  });

  const result = await asyncOperation();
  eventEmitter.emit('operationCompleted', result);
}

performAsyncWithPubSub();

在这个例子中,我们创建了一个EventEmitter类来实现发布订阅模式。asyncOperation函数模拟一个异步操作,在两秒后返回一个结果。performAsyncWithPubSub函数使用发布订阅模式,在异步操作完成后发布一个事件,然后订阅这个事件的回调函数会被执行并打印出结果。

5. generator函数

6. promise all

const fetchRes = (res) => {
    return new Promise((resolve, reject) => {
        resolve(res);
    }).then((data) => {
        return data
    }).catch((error) => {
        console.log(error);
    })
}
const fetchAll = () => {
    return Promise.all([fetchRes('res1'), fetchRes('res2')]).then((data) => {
        console.log(data);
    }).catch((error) => {
        console.log(error);
    }).finally(() => {
        console.log('done');
    })    
}

7. 预加载资源

import { Image } from 'react-native';

// 预加载图像
Image.prefetch('https://example.com/image.jpg')
 .then(() => console.log('Image preloaded successfully'))
 .catch(error => console.error('Error preloading image:', error));

8. addEvent Listener事件监听

二、异步处理场景

  1. 网络请求
  2. 定时任务
  3. 事件绑定
  4. 大量数据处理web worker
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
</head>

<body>
  <script>
    // 创建 Web Worker
    const worker = new Worker('worker.js');

    // 生成大量数据
    const largeData = Array.from({ length: 1000000 }, (_, i) => i);

    // 向 Web Worker 发送数据进行处理
    worker.postMessage(largeData);

    // 监听 Web Worker 的消息
    worker.addEventListener('message', event => {
      console.log('处理后的数据:', event.data);
    });
  </script>
</body>

</html>

Web Worker 文件(worker.js):

self.addEventListener('message', event => {
  const data = event.data;
  // 模拟大量数据处理,这里只是简单地将每个元素乘以 2
  const processedData = data.map(item => item * 2);
  // 将处理后的数据发送回主页面
  self.postMessage(processedData);
});

主页面生成了一个包含一百万个数字的大量数据数组,并将其发送给 Web Worker 进行处理。Web Worker 接收到数据后,对每个元素进行简单的乘以 2 的操作,并将处理后的数据发送回主页面。主页面通过监听 Web Worker 的消息事件来获取处理后的数据并进行输出。
通过使用 Web Worker,可以在后台线程中异步处理大量数据,避免阻塞主页面的 UI 线程,提高应用的性能和响应性。

三、Promise

1、特点

  • Promise状态有Pending进行中Rejected已失败Fullfilled已成功
  • 状态不可逆,第一次成功就永久,是fullfilled,第一次失败就永久是rejected
  • Promise中有thorw的话,就相当于reject

2、代码实现一个Promise

要实现一个自建的MyPromise实例,需要根据Promise的特点进行几个方面的处理:

  • Promise的初始状态是pending
  • resolve、reject需要绑定this,确保永远指向当前的MyPromise实例
  • 状态非pending时不可变
  • 如果有throw相当于执行了reject,这里用try、catch实现

实现了以上的功能点,基本可以自建一个MyPromise实例了,不过还缺少then

  • then是绑定在Promise上的Promise.prototype.then
  • 第一个参数是resolved的回调函数,第二个参数是rejected的回调函数
  • then还可以链式调用
  • then是微任务,要在主任务完成后执行,因为都在微任务列表中

大体上有以下几个步骤:

  1. 声明一个类class HePromise,HePromise里创建私有属性:状态value(resolve和reject处理传入then的value值)、resolves列表rejects列表
  2. constructor内绑定resolve、reject到this,保证永远指向当前的实例。
  3. resolve函数,状态不可逆,非pending时返回否则改为fulfilled,将传入的参数设置为this.value, 留作then时使用,将resolves内的resolve函数都从头一个个取出,执行函数。
  4. reject函数的思路和resolve一样,也是非pending时返回,否则状态改为rejected
  5. then函数返回一个新的实例对象HePromise,先处理状态,pengding时将resolve和reject传入对应的private列表,否则fulfilled执行resolve逻辑,rejected执行reject逻辑;resolve逻辑:如果传入的resolveFunc函数执行结果resolvedVal是HePromise对象,那么继续递归then,否则resolve(resolvedVal), 执行resolve函数;reject的部分逻辑也一样处理即可。
    官方提示注意:
    在使用then方法是,不要在then方法中定义rejected状态的回调函数,而应总是使用catch方法
type FuncType = (...args: any[]) => any;

type ExecutorFunc = (resolveFunc: FuncType, rejectFunc?: FuncType) => any;

enum STATUS {
  PENDING = 'pending',
  FULFILLED = 'fulfilled',
  REJECTED = 'rejected',
}

export class HePromise {
  private status = STATUS.PENDING;
  private value = undefined;
  private resolves: FuncType[] = [];
  private rejects: FuncType[] = [];

  constructor(executor: ExecutorFunc) {
    const { resolve, reject } = this;
    // executor是一个函数,它接受两个参数,通常被命名为 resolve 和 reject。
    //这两个参数本身也是函数
    //分别用于在异步操作成功时调用以改变 Promise 的状态为 fulfilled(完成)并传递结果值
    //以及在异步操作失败时调用以改变 Promise 的状态为 rejected(拒绝)并传递错误原因。
    executor(resolve, reject);
  }

  private resolve = (resolvedVal: any) => {
    const { resolves, status } = this;
    // 状态不可逆
    if (status !== STATUS.PENDING) return;
    this.status = STATUS.FULFILLED;
    // 将结果值设置为this.value,用于传入then
    this.value = resolvedVal;
    while (resolves.length) {
      const cb = resolves.shift();
      if (cb) cb(resolvedVal);
    }
  };

  private reject = (rejectedVal: any) => {
    const { rejects, status } = this;
    if (status !== STATUS.PENDING) return;
    this.status = STATUS.REJECTED;
    this.value = rejectedVal;
    while (rejects.length) {
      const cb = rejects.shift();
      if (cb) cb(rejectedVal);
    }
  };

  then(resolveFunc: FuncType, rejectFunc?: FuncType): HePromise {
  	// then函数传入两个方法,相当于resolve和reject
  	// 如果不是方法,返回参数为value的resolveFunc函数
    typeof resolveFunc !== 'function' ? (resolveFunc = value => value) : null;
    typeof rejectFunc !== 'function'
      ? (rejectFunc = reason => {
          throw new Error(reason instanceof Error ? reason.message : reason);
        })
      : null;

    return new HePromise((resolve, reject) => {
      const resolvedFn = (val: any) => {
        try {
          const resolvedVal = resolveFunc(val);
          resolvedVal instanceof HePromise
            ? resolvedVal.then(resolve, reject)
            : resolve(resolvedVal);
        } catch (error) {
          if (reject) reject(error);
        }
      };
      this.resolves.push(resolvedFn);

      const rejectedFn = (val: any) => {
        if (rejectFunc) {
          try {
            const rejectedVal = rejectFunc(val);
            rejectedVal instanceof HePromise
              ? rejectedVal.then(resolve, reject)
              : resolve(rejectedVal);
          } catch (error) {
            if (reject) reject(error);
          }
        }
      };

      switch (this.status) {
        case STATUS.PENDING:
          this.resolves.push(resolvedFn);
          this.rejects.push(rejectedFn);
          break;
        case STATUS.FULFILLED:
          resolvedFn(this.value);
          break;
        case STATUS.REJECTED:
          rejectedFn(this.value);
          break;
      }
    });
  }
}

3、Promise.all

1.Promise.all的特点:

  • 接受一个Promise数组,如果数组中有非Promise项,此项当做成功
  • 如果所有Promise都成功,则返回成功的结果数组
  • 如果有一个Promise失败,则返回这个失败结果

2.代码实例

const fetchDate = (str)=>{
	return new Promise((resolve,reject)=>{
		fetch(str)
		.then((response)=>{
			if(!response.ok){
				reject(new Error(`HTTP error! Status: ${response.status}`));
			}
			return response.json;
		}).then((data)=>{
			resolve(data);
		}).catch((error)=>{
			console.log(error)
		})
	})
}
const fetchAll = ()=>{
	return new Promise.all([fetchDate1,fetchDate2])
	.then((data)=>{
		console.log(data);
	}).catch((error)=>{
		console.log(error)
	})
}

3. 手写代码实现一个Promise.all

这个方法是一个静态方法,可以在实例上获取

new Promise().all([])

也可以在类上直接获取

Promise.all()

具体实现如下:
看到上面的代码实例,我们在手写实现的时候需要给每个promise实例加上两个参数statusvalue

static all(promises){
	let result = [];
	let count = 0;
	return new Promise((resolve,reject)=>{
		const addData = (index, value)=>{
			result[index] = value;
			count++;
			if(count === promises.length){
				resolve(result);
			}			
		}
		promises.forEach((promise, index)=>{
			if(promise instanceof Promise){
				promise.then((data)=>{
					addData(index,data)
				}).catch((e)=>
					reject(e);
					return;
				)
			} else {
				addData(index,promise)
			}
		})
	})
}

4、Promise.race

1. Promise.all的特点:

  • 接受一个Promise数组,如果数组中有非Promise项,此项当做成功
  • 哪个Promise最快得到结果,就返回那个结果,无论成功失败

2.代码实例

const arr = [fetchData1, fetchData2]
const promiseRace = (arr)=>{
	return new Promise.race((arr))
	.then((res)=>{
		return res
	}).catch((e)=>
		reject(e);
	)
}

3. 手写代码实现一个Promise.race

一样,我们还是用static格式来手写一个race方法

static race(promises){
	return new Promise((resolve,reject)=>{
		promises.forEach((promise)=>{
			if(promise instanceof Promise){
				promise.then((res)=>{
					resolve(res);
					return
				}).catch((err)=>{
					reject(err);
					return;
				})
			} else {
				resolve(err);
			}
		})
	})
}

5、Promise.allSettled

1. 与Promise.all()区别

Promise.all()不同的是,Promise.allSettled()不会因为其中一个 promise 被拒绝而立即拒绝,而是会等待所有的 promise 都有结果后,无论结果是成功还是失败,都会将每个 promise 的状态和值或错误信息记录下来并返回。

2、代码实例

 const allSettled = (promises) => {
     return Promise.allSettled(promises)
     .then((promise) => {
         if (promise.status === 'fulfilled') {
             console.log(promise.value);      
         } else {
             console.log(promise.reason);
         }
     })
 }

3、手写代码实现allSettled

看到上面的代码实例,我们在手写实现的时候需要给每个promise实例加上两个参数statusvalue

const myAllSettled = (promises)=>{
	let res = [];
	let count = 0;
	return new Promise((resolve,reject)=>{
		const addData = (status, value, i)=>{
			res[i]={
				status,
				value
			};
			count++;
			if(count === promises.length){resolve(res)};
		}
	})
	promises.forEach((promise,index)=>{
		if(promise instanceof Promise){
			promise.then(res=>{
				addData('fullfilled', res, index);
			},err=>{
				addData('rejected', res, index);
			})
		} else {
			addData('fullfilled', promise, index);
		}
	})
}

6、Promise.any

1. Promise.any 介绍

Promise.any()方法接收一个可迭代对象(例如数组),其中包含多个 Promise 实例。这个方法返回一个新的 Promise,只要可迭代对象中的其中一个 Promise 成功,这个新的 Promise 就会成功,并且返回第一个成功的 Promise 的值。如果可迭代对象中的所有 Promise 都失败了,那么这个新的 Promise 就会失败,并返回一个AggregateError错误对象,这个错误对象包含所有失败的 Promise 的错误信息。

2.代码实例

any和all的区别就在于,any是任意一个就行,所以只返回一个

Promise.any([promise1, promise2, promise3])
.then(result => {
  console.log(result); // 'Success from promise3'
})
.catch(error => {
  console.error(error);
});

3、手写代码实现

function myPromiseAny(promises) {
  return new Promise((resolve, reject) => {
    const errors = [];
    let fulfilledCount = 0;

    if (!Array.isArray(promises) || promises.length === 0) {
      return reject(new AggregateError([], "No Promises provided"));
    }

    for (let i = 0; i < promises.length; i++) {
      Promise.resolve(promises[i])
       .then(value => {
          resolve(value);
        })
       .catch(error => {
          errors.push(error);
          fulfilledCount++;
          if (fulfilledCount === promises.length) {
            reject(new AggregateError(errors));
          }
        });
    }
  });
}

四、手写一个scheduler

class Scheduler{
	constructor(maxCurrent){
		this.maxCurrent = maxCurrent;
		this.runningNum = 0;
		this.queue = []
	}
	add = (task)=>{
		return new Promise((resolve,reject)=>{
			this.queue.push({task,resolve,reject});
			this.runQueue()
		})
	}
	runQueue = ()=>{
		if(this.maxCurrent>this.runningNum&&this.queue.length>0){
			const{task, resolve,reject} = this.queue.shift();
			this.runningNum++;
			task()
			.then((res)=>{
				resolve(res);
			}).catch((err)=>{
				reject(err)
			}).finally(()=>{
				this.runningNum--;
				this.runQueue()
			})
		}
	}
}
const scheduler = new Scheduler(2);

在这个实现中,Scheduler 类接受一个参数 maxConcurrent,表示同时运行的最大任务数。通过维护一个任务队列和当前正在运行的任务计数,确保在任何时候都不会超过指定的最大并发数。当一个任务完成时,会从任务队列中取出下一个任务并执行。

五、async/ await

1、使用

  • 用同步方式执行异步操作,防止then不停嵌套
  • await只能在async函数中使用
  • 如果想起到同步效果,await后面最好跟Promise
  • async执行完会返回一个fullfilled状态的Promise,如果想得到返回值,就加一个return,有没有值就看return了
const fn = async(url)=>{
    const res1 = await fetchData(url);
    const res2 = await fetchData(res1.nextUrl);
   	return res2;
}

上面的代码就是一个一个执行,并且第一个执行的返回值传给了第二次作为参数,最后return返回最终结果。

2、手写代码实现async/ await

async/ await是generator的语法糖,区别在于

  • generator函数返回不是Promise,async返回Promise
  • generator需要执行相应的操作,才能等同于async排队效果
  • generator函数执行操作是不完善的,不确定有几个yield,不确定嵌套几次

因此我们基于generator函数手写async/ await的功能实现
首先是一个generator函数:

const f1 = (nums) => {
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve(nums*2)
        },1000)
    })
}
const gen = function*() {
    const nums = yield f1(10);
    const num2 = yield f1(nums);
    return num2;
}

使用递归方法,将生成器函数产生的数据不断调用next(),直到执行完成,这里有一个判断是否执行完成的方法generator.next().done

const asyncPromise = (generatonFn) => {
    const generator = generatonFn();
    try {
        handleResult(generator.next());
    } catch (error) {
        return Promise.reject(error);
    }
    const handleResult = (result) => {
        if (result.done) {
            return Promise.resolve(result.value);
        }
        return Promise.resolve(result.value).then((res)=>{
            handleResult(generator.next(res))
        }).catch((error)=>{
            generator.throw(error);
        })
    }
}

四、为什么Promise没有取消机制

在JavaScript中,Promise是用于处理异步操作的对象,它代表一个异步操作的最终完成(或失败)及其结果值。然而,JavaScript的Promise并不提供内置的取消(cancel)机制。
Promise是经过了深思熟虑,才不自带取消功能的!!!

这篇文章,将围绕着设计的哲学,以及从状态机的角度,解释为什么不需要cancel。
即使如此,文章最后部分,还是会提供一些方法,来实现一下cancle。

设计的哲学

设计理念

Promise的设计初衷是为了简化回调函数的使用,使得处理异步操作的代码更加简洁和可读。其设计重点在于处理异步操作的成功和失败,而不是控制操作的生命周期。
取消机制会引入复杂性,尤其是对于依赖于多个Promise的情况,例如Promise.all或Promise.race。如果某个Promise被取消,其影响可能会传递给其他依赖于它的Promise,导致意外的行为和难以调试的问题。

资源管理

异步操作通常涉及到外部资源,如网络请求、定时器等。Promise取消机制需要能够正确管理和释放这些资源。实现一个通用且可靠的资源管理机制非常复杂,并且可能因不同的资源类型而异。

取消语义不明确

如果一个Promise可以被取消,那么需要明确如何处理其已完成的状态。特别是,处理已经部分完成或即将完成的操作,可能会导致不一致的状态。

状态机:简单就是美

Promise的状态机

在输入一个状态时,只得到一个固定的状态。
在这里插入图片描述

一个Promise可以被看作是一个简单的状态机,它有以下几种状态:

  • Pending(进行中) :初始状态,表示异步操作尚未完成。
  • Fulfilled(已完成) :表示异步操作成功完成,并返回了一个值。
  • Rejected(已拒绝) :表示异步操作失败,并返回了一个原因(错误)。

状态转换规则如下:

  • 从Pending状态可以转换到Fulfilled状态。
  • 从Pending状态可以转换到Rejected状态。

一旦转换到Fulfilled或Rejected状态,Promise的状态就不可再改变。

取消功能的复杂性

引入取消功能意味着需要增加一个新的状态——“Cancelled(已取消)”。这会使状态机的设计变得更加复杂,因为需要考虑更多的状态转换和边界情况。
如果我们引入“Cancelled”状态,状态机的状态和转换规则将变成:

  1. Pending(进行中) :

可以转换到Fulfilled。
可以转换到Rejected。
可以转换到Cancelled。

  1. Fulfilled(已完成) :状态不可变。
  2. Rejected(已拒绝) :状态不可变。
  3. Cancelled(已取消) :状态不可变。

这种增加的复杂性会导致以下问题:

  • 状态转换冲突:需要明确地处理在Pending状态下多次转换的情况。例如,如果一个Promise在Pending状态下同时尝试转换到Fulfilled和Cancelled,应该优先处理哪一个?
  • 副作用处理:许多异步操作(如网络请求、文件读写等)具有副作用。取消这些操作需要确保所有相关的资源都被正确地清理,这不仅增加了实现的复杂性,还可能导致不一致的状态。
  • 链式操作:Promise通常被链式调用( .then().catch() )。如果一个中间的Promise被取消,如何处理后续链式操作也是一个难题。例如,Promise.all或Promise.race的行为如何改变?

如何实现取消功能

尽管标准的Promise没有内置的取消功能,可以通过一些方法来实现类似的功能。例如,使用AbortController来取消网络请求,或者使用自定义的Promise包装器来支持取消。

使用AbortController

对于Fetch API,可以使用AbortController来取消请求:

const controller = new AbortController();
const signal = controller.signal;

fetch('https://www.baidu.com', { signal })
  .then(response => response)
  .then(data => console.log(data))
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('Fetch aborted');
    } else {
      console.error('Fetch error:', err);
    }
  });

// 取消请求

controller.abort();

自定义Promise包装器
也可以创建一个支持取消的自定义Promise包装器:

class CancellablePromise {
  constructor(executor) {
    this._hasCanceled = false;
    
    this._promise = new Promise((resolve, reject) => {
      executor(
        value => this._hasCanceled ? reject({ canceled: true }) : resolve(value),
        reason => this._hasCanceled ? reject({ canceled: true }) : reject(reason)
      );
    });
  }
  
  cancel() {
    this._hasCanceled = true;
  }

  then(onFulfilled, onRejected) {
    return this._promise.then(onFulfilled, onRejected);
  }

  catch(onRejected) {
    return this._promise.catch(onRejected);
  }
}

// 使用自定义的CancellablePromise
const cancellablePromise = new CancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('Completed!'), 1000);
});

cancellablePromise.then(
  result => console.log(result),
  err => {
    if (err.canceled) {
      console.log('Promise was canceled');
    } else {
      console.error('Promise error:', err);
    }
  }
);

// 取消Promise

cancellablePromise.cancel();

虽然标准的Promise没有内置取消功能,但可以通过这些方法来实现取消逻辑,根据实际需求选择合适的方案。

结语

虽然JavaScript的Promise没有内置取消功能,但这并不意味着我们无法实现取消功能。通过理解Promise的设计哲学和状态机模型,我们可以更好地掌握其使用方法,并通过巧妙的编程技巧实现我们需要的功能

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

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

相关文章

SpringSecurity Oauth2 - 密码模式完成身份认证获取令牌 [自定义UserDetailsService]

文章目录 1. 授权服务器2. 授权类型1. Password (密码模式)2. Refresh Token&#xff08;刷新令牌&#xff09;3. Client Credentials&#xff08;客户端凭证模式&#xff09; 3. AuthorizationServerConfigurerAdapter4. 自定义 TokenStore 管理令牌1. TokenStore 的作用2. Cu…

嵌入式Linux C应用编程指南-高级I/O(速记版)

第十三章 高级I/O 13.1 非阻塞I/O 阻塞其实就是进入了休眠状态&#xff0c;交出了 CPU 控制权。比如 wait()、pause()、sleep()等函数都会进入阻塞。 阻塞式 I/O 顾名思义就是对文件的 I/O 操作&#xff08;读写操作&#xff09;是阻塞式的&#xff0c;非阻塞式 I/O 同理就是对…

SpringSecurity Oauth2 - 访问令牌续期

文章目录 1. 访问令牌的续期2. CustomUserDetailsService3. 配置 AuthorizationServerEndpointsConfigurer4. 测试项目 1. 访问令牌的续期 在Spring Security OAuth2中&#xff0c;访问令牌的续期通常是通过使用**刷新令牌&#xff08;Refresh Token&#xff09;**来实现的。当…

走进酒厂,探寻白酒酿造的奥秘

在华夏大地深处&#xff0c;隐藏着一座座充满神秘色彩的酒厂&#xff0c;它们是白酒酿造的地方&#xff0c;也是中华酒文化的摇篮。今天&#xff0c;就让我们一起走进这些酒厂&#xff0c;探寻白酒酿造的奥秘&#xff0c;感受豪迈白酒&#xff08;HOMANLISM&#xff09;的不同魅…

当网络适配器的Wireless出现感叹号

1.出现如下情况 链接&#xff1a; &#xff1a;一招搞定Intel(R) Wireless-AC 9560显示感叹号&#xff0c;无法打开wifi模块&#xff01;_intel(r)wireless-ac9560感叹号-CSDN博客z 重点&#xff1a; 原因是因为电脑静电的问题。

昇腾AI处理器的计算核心 - AI Core即DaVinci Core

昇腾AI处理器的计算核心 - AI Core即DaVinci Core flyfish 从一段代码的解释开始 template <typename T> class GlobalTensor { public:void setGlobalBuffer(T* buffer, uint32_t buffersize) {// 在这里实现设置全局缓冲区的逻辑} };语法的说明&#xff0c;主要用于…

封装_私有类字段和方法

前言 在 JavaScript 中&#xff0c;封装、私有类字段和方法是面向对象编程的一种重要特性。它们允许你将数据&#xff08;属性&#xff09;和对数据的操作&#xff08;方法&#xff09;组合在一起&#xff0c;并控制访问权限&#xff0c;从而提高代码的安全性和可维护性。私有…

异步编程详解

1.什么是async std::async:是一个函数模板,用于启动一个异步任务。它接受一个可调用的对象(如函数、Lambda表达式、函数对象)作为参数,并在一个单独的线程上异步执行对象。std::async自动管理异步任务的生命周期,并返回一个std::future对象,该对象用于获取异步操作的结果。 2.什…

【Java】—— Java面向对象进阶:继承小练习-Java中实现圆柱体类及其体积计算

目录 1. 定义圆类&#xff08;Circle&#xff09; 2. 定义圆柱体类&#xff08;Cylinder&#xff09; 3. 测试圆柱体类 4. 总结 在Java中&#xff0c;我们可以通过面向对象的方式来模拟现实世界中的物体&#xff0c;比如圆柱体。本篇文章将通过一个简单的示例来展示如何定义…

全国大学生数学建模竞赛系统使用手册

注意&#xff01;国赛是学校统一报名&#xff0c;所以如果在操作上有任何不清楚的地方&#xff0c;一定要在赛前即使询问自己学校组织数模的老师&#xff01;并详细阅读本文和官网通知&#xff0c;以及&#xff1a;数模国赛提交MD5码和论文的坑&#xff01; 数模比赛的建模手、…

【Python报错已解决】“ModuleNotFoundError: No module named ‘timm‘”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.1 报错示例&#xff1a;当我们尝试导入timm库时&#xff0c;可能会看到以下错误信息。…

颠覆传统:基于全文索引驱动下的高效一对多表结构设计!

首发公众号&#xff1a;赵侠客 引言 在数据库表结构设计中&#xff0c;一对多&#xff08;1:N&#xff09;关系的处理是非常常见需求&#xff0c;如一个用户有多个分类或角色。传统关系型数据库表设计方式通常要包括三张表&#xff1a;用户表、分类表、以及用户与分类之间的关…

LC开源电路的学习(一)

TI的升压芯片&#xff0c;电压虽然能升高&#xff0c;但是带来的问题就是最大电流大幅降低&#xff1a; CC1和CC2芯片接快充芯片之后&#xff0c;直接接到单片机的下载口&#xff1a; 这个有点意思&#xff0c;用导线换电阻&#xff1a; 、 PD快充芯片CH224K需要连接typeC的D…

华为云征文|基于Flexus云服务器X实例的应用场景-部署脚手架开源项目若依

&#x1f534;大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 先看这里 写在前面**Flexus X实例**的云服务器简介环境准备若依项目拉取导入数据库启动本地项目&#xff08;后端&#xff09;启动本地项目&#xff08;前端&#xff09;打包后…

图片转为PDF怎么弄?看这里,三款软件助你一键转换!

嘿&#xff0c;朋友们&#xff01;现在信息这么多&#xff0c;图片在我们学习、工作、生活中帮了大忙。但有时候&#xff0c;我们想把图片整理好、分享给别人或者打印出来&#xff0c;PDF格式就特别合适。PDF文件不管在哪儿打开&#xff0c;内容都不会变样&#xff0c;还能加密…

Pandas 9-绘制柱状图

1. 准备数据 首先&#xff0c;需要准备一个DataFrame。 import pandas as pd # 创建一个DataFrame data { Name: [Alice, Bob, Charlie, David], Age: [24, 27, 22, 32], City: [New York, Los Angeles, Chicago, Houston], Score: [85, 92, 78, 88]} df pd.…

【生成模型系列(初级)】自编码器——深度学习的数据压缩与重构

【通俗理解】自编码器——深度学习的数据压缩与重构 第一节&#xff1a;自编码器的类比与核心概念 1.1 自编码器的类比 你可以把自编码器想象成一个“智能压缩机”&#xff0c;它能够把输入的数据&#xff08;比如图片&#xff09;压缩成一个更小的表示&#xff08;编码&#…

超声波模块

HCSR04超声波模块是一种常用的测距模块&#xff0c;它通过检测超声波发射后遇到障碍物所反射的回波&#xff0c;从而测量出与障碍物之间的距离。以下是对HCSR04超声波模块的详细讲解&#xff1a; 一、模块组成与工作原理 组成&#xff1a;HCSR04超声波模块主要由两个压电陶瓷超…

【我的Android进阶之旅】快来给你的Kotlin代码添加Markdown格式的注释吧!

文章目录 一、 传统 HTML 格式注释二、 Markdown 格式注释三.、Markdown格式注释详解3.1. 基础语法3.1.1 单行注释3.1.1 多行注释3.2 标题3.3 列表3.4 加粗和斜体3.5 代码块3.6 链接3.7 引用3.8 表格3.9. 图片3.10. 示例代码3.11. 注释模板的使用场景3.12 实例示例四、总结在 A…

2024年9月深圳200万~300万的三房笔记

​整理了2024年9月深圳200万~300万的三房笔记&#xff0c;数据可能有​出入。有些商品房数据是我看到工抵房的数据&#xff0c;群里说工抵房的房价数据需要乘以1.2就比较接近当前现场的价格​。对于我个人来说关注地铁&#xff0c;即是否方便打工还有价格​。看着一些商品房的工…