ES6 await

本文围绕async函数展开,介绍其是Generator函数的语法糖及四点改进。阐述基本用法,指出返回Promise对象及状态变化规则。详细说明await命令,包括对不同对象的处理和错误处理机制。还提及使用注意点、实现原理,并与其他异步方式作比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

async函数

含义

他就是Generator函数的语法糖,generator函数读取两个文件

const fs=require('fs');
const readFile=function(fileName){
	return new Promise(function(resolve,reject){
		fs.readFile(fileName,function(error,data){
			if(error) return reject(error);
			resolve(data);
			});
		});
};

const gen=function* (){
	const f1=yield readFile('/etc/fstab');
	const f2=yield readFile('/etc/shells');
	console.log(f1.toString());
	console.log(f2.toString());
}

上面的代码gen写成async就是这样

const asyncReadFile=async function (){
	const f1=await readFile('/etc/fstab');
	const f2=await readFile('/etc/shells');
	console.log(f1.toString());
	console.log(f2.toString());
} 

async对Generator函数的改进,体现在一下四点

  1. 内置执行器 执行与普通函数一样
  2. 更好的语义
  3. 更广的适用性
  4. 返回值是Promise

基本用法

async function getStockPriceByName(name){
	const symbol=await getStockSymbol(name);
	const stockPrice=await getStockPrice(symbol);
	return stockPrice;
}//返回一个promise
getStockPriceByName('goog').then(function(result){
	console.log(result);
	});

另一个例子

function timeout(ms){
	return new Promise((resolve)=>{
		setTimeout(resolve,ms);
		});
}
async function asyncPrint(value,ms){
	await timeout(ms);
	console.log(value);
}
asyncPrint('hello world', 50);

上面代码50ms输出helloworld
由于saync函数返回的是Promise对象,可以作为await命令的参数,所以,上面的例子也可以写成下面形式

async function timeout(ms){
	await new Promise((resolve)=>{
		setTimeout(resolve,ms);
		});
}
async function asyncPrint(value,ms){
	await timeout(ms);
	console.log(value);
}
asyncPrint('hello world',50);

async函数有多种使用形式

//函数声明
async function foo(){}
//函数表达式
const foo = async function() {};
//对象的方法
let obj={ async foo(){} };
obj.foo().then(...)

//Class的方法
class Storage{
	constructor(){
		this.cachePromise = caches.open('avatars');
	}
	async getAvatar(name){
		const cache=await this.cachePromise;
		return cache.match(`/avatars/${name}.jpg`);
	}
}
const storage=new Storage();
storage.getAvatar('jake').then(...);

//箭头函数
const foo = async ()=>{};

语法

async函数语法总体比较简单,难点是错误处理机制

返回Promise对象

函数内的返回值成为then方法回调函数的参数。

async function f(){
	return "hello world";
}
f().then(v => console.log(v));//hello world

async函数内部抛出的错误会导致返回的Promise对象变为reject状态,抛出的错误对象会被catch方法回调函数接收

async function f(){
	throw new Error('出错了');
}
f().then(
	v=>console.log(v),
	e=>console.log(e)
	)
	//Error: 出错了

Promise对象的状态变化

async函数返回的Promise对象,必须等await命令后面的Promise对象执行完,才会发生状态改变。

async function getTitle(url){
	let response=await fetch(url);
	let html=await response.text();
	return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle("xxxxxx").then(console.log);

上述getTitle内的操作全部完成,才会执行console.log

await命令

await命令后面是一个Promise对象,返回该对象的结果,如果不是Promise对象返回对应的值。

async function f(){
	return await 123;
}
f().then(v => console.log(v));

另一种情况返回thenable对象,await会将其等同Promise对象

class Sleep{
	constructor(timeout){
		this.timeout=timeout;
	}
	then(resolve,rejcet){
		const startTime=Date.now();
		setTimeout(
		()=>resolve(Date.now()-startTime),
		this.timeout;
			);
	}
}
(async ()=>{
	const sleepTime = await new Sleep(1000);
	console.log(sleepTime);
	})

上面代码await命令后面是Sleep对象实例,定义了then,await将其视为Promise处理。
实现简单休眠

function sleep(interval){
	return new Promise(resolve=>{
		setTimeout(resolve,interval);
		})
}
//用法
async function one2FiveInAsync(){
	for(let i=1;i<=5;i++){
		console.log(i);
		await sleep(1000);
	}
}

one2FiveInAsync();

await命令后面Promise对象如果变为reject状态,则reject参数会被catch方法回调函数接收

async function f(){
	await Promise.reject("出错了");
}
f()
.then(v=>console.log(v))
.catch(e=>console.log(e));
//出错了

注意上面代码await没有return,但是reject方法的参数依然传入了catch方法的回调函数。
任何一个await语句后面的Promise对象变为reject状态,整个async函数都会中断。

async function f(){
	await Promise.reject('出错了');
	await Promise.resolve('hello world');//不会执行
}

第二行代码不会执行,因为await语句状态变成了reject
如果需要即使前面一个异步操作失败,也不要中断后面的异步操作,可以将await放在try…catch结构里面。

async function f(){
	try{
		await Promise.reject('出错了');
	}catch(e){

	}
	return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
//hello world

另一种方法是await后面的Promise对象再跟一个catch方法,处理前面可能出现的错误。

async function f(){
	await Promise.reject('出错了')
	.catch(e => console.log(e));
	return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v));
//出错了 
//hello world

错误处理

如果await后面的异步操作出错,等同于async函数返回的Promise对象被reject

async function f(){
	await new Promise(function(resolve,reject){
		throw new Error('出错了');
		});
}
f()
.then(v => console.log(v))
.catch(e => console.log(e));

上面代码async函数f执行后,await后面的Promise对象抛出一个错误对象,导致catch方法回调函数被调用,参数为抛出的错误对象
防止出错的方法,也可以将其放在try…catch中

async function f(){
	try{
		await new Promise(function(resolve,reject){
			throw new Error('出错了');
			});
	}catch(e){

	}
	return await('hello world');
}

如果有多个await命令,可以统一放在try…catch中

async function main(){
	try{
		const val1=await firstStep();
		const val2 = await secondStep(val1);
    const val3 = await thirdStep(val1, val2);

    console.log('Final: ', val3);
	}catch (err) {
    console.error(err);
  }
}

下面例子使用try…catch结构 实现多次重复尝试

const superagent = require('superagent');
const NUM_RETRIES = 3;

async function test() {
  let i;
  for (i = 0; i < NUM_RETRIES; ++i) {
    try {
      await superagent.get('http://google.com/this-throws-an-error');
      break;
    } catch(err) {}
  }
  console.log(i); // 3
}

test();

上面代码,成功跳出,失败catch捕捉,下一轮

使用注意点

同时触发

let [foo,bar]=await Promise.all([getFoo(),getBar()]);//1
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;//2

并发执行

async function dbFuc(db){
	let docs=[{},{},{}];
	let promises=docs.map((doc)=>db.post())

	let results=await Promise.all(promises);
	console.log(results);
}

async函数保留运行栈

const a = async()=>{
	await b();
	c();
}

async 函数实现原理

将Generator和自执行器包装在一个函数里

async function fn(args){

}
//等同于
function fn(args){
	return spawn(function* (){

		})
}

具体实现

function spawn(genF){
	return new Promise(function(resolve,reject){
		const gen=genF();
		function step(nextF){
			let next;
			try{
				next=nextF();
			}catch(e){
				return reject(e);
			}
			if(next.done){
				return resolve(next.value);
			}
			Promise.resolve(next.value).then(function(v){
				step(function(){ return gen.next(v); })
				},function(e){
					step(function(){ return gen.throw(e); })
					});
		}
		step(function(){ return gen.next(undefined); });
		})
}

与其他异步比较

并发远程请求

async function logInOrder(urls){
	const textPromises=urls.map(async url->{
		const response = await fetch(url);
		return response.text();
		});
	for(const textPromise of textPromises){
		console.log(await textPromise);
	}
}
### RT-DETRv3 网络结构分析 RT-DETRv3 是一种基于 Transformer 的实时端到端目标检测算法,其核心在于通过引入分层密集正监督方法以及一系列创新性的训练策略,解决了传统 DETR 模型收敛慢和解码器训练不足的问题。以下是 RT-DETRv3 的主要网络结构特点: #### 1. **基于 CNN 的辅助分支** 为了增强编码器的特征表示能力,RT-DETRv3 引入了一个基于卷积神经网络 (CNN) 的辅助分支[^3]。这一分支提供了密集的监督信号,能够与原始解码器协同工作,从而提升整体性能。 ```python class AuxiliaryBranch(nn.Module): def __init__(self, in_channels, out_channels): super(AuxiliaryBranch, self).__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(out_channels) def forward(self, x): return F.relu(self.bn(self.conv(x))) ``` 此部分的设计灵感来源于传统的 CNN 架构,例如 YOLO 系列中的 CSPNet 和 PAN 结构[^2],这些技术被用来优化特征提取效率并减少计算开销。 --- #### 2. **自注意力扰动学习策略** 为解决解码器训练不足的问题,RT-DETRv3 提出了一种名为 *self-att 扰动* 的新学习策略。这种策略通过对多个查询组中阳性样本的标签分配进行多样化处理,有效增加了阳例的数量,进而提高了模型的学习能力和泛化性能。 具体实现方式是在训练过程中动态调整注意力权重分布,确保更多的高质量查询可以与真实标注 (Ground Truth) 进行匹配。 --- #### 3. **共享权重解编码器分支** 除了上述改进外,RT-DETRv3 还引入了一个共享权重的解编码器分支,专门用于提供密集的正向监督信号。这一设计不仅简化了模型架构,还显著降低了参数量和推理时间,使其更适合实时应用需求。 ```python class SharedDecoderEncoder(nn.Module): def __init__(self, d_model, nhead, num_layers): super(SharedDecoderEncoder, self).__init__() decoder_layer = nn.TransformerDecoderLayer(d_model=d_model, nhead=nhead) self.decoder = nn.TransformerDecoder(decoder_layer, num_layers=num_layers) def forward(self, tgt, memory): return self.decoder(tgt=tgt, memory=memory) ``` 通过这种方式,RT-DETRv3 实现了高效的目标检测流程,在保持高精度的同时大幅缩短了推理延迟。 --- #### 4. **与其他模型的关系** 值得一提的是,RT-DETRv3 并未完全抛弃经典的 CNN 技术,而是将其与 Transformer 结合起来形成混合架构[^4]。例如,它采用了 YOLO 系列中的 RepNCSP 模块替代冗余的多尺度自注意力层,从而减少了不必要的计算负担。 此外,RT-DETRv3 还借鉴了 DETR 的一对一匹配策略,并在此基础上进行了优化,进一步提升了小目标检测的能力。 --- ### 总结 综上所述,RT-DETRv3 的网络结构主要包括以下几个关键组件:基于 CNN 的辅助分支、自注意力扰动学习策略、共享权重解编码器分支以及混合编码器设计。这些技术创新共同推动了实时目标检测领域的发展,使其在复杂场景下的表现更加出色。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值