如何将 JS Promises 翻译成 Rust
How to translate JS Promises to Rust
目前我正在编写一个纯 Rust MQTT5 库(我知道那里有现有的库,但我更想学习 Rust)并且我偶然发现了这个问题。
我在 tokio 1.0.1 中使用最新的稳定 Rust。
当我通过网络发送一个数据包时,我经常期待服务器的响应(下面的示例 PingReq/PingAck、Ping/Pong)。
省略了很多有关超时和数据包冲突的逻辑,我在 JavaScript 中编写了一个简化版本的逻辑(因为我对此非常了解)。
这种逻辑将如何转化为 Rust 及其未来?
或者更清楚:我能以某种方式重新创建 awaitPackage + onIncomingPacket 的 resolve() 回调函数行为吗?
class Client {
awaitedPacketTypes = {};
/**
* a ping consist of a send ping and a receive pong
*/
async ping(){
await this.sendPacket("Ping");
return await this.awaitPackage("Pong");
}
async sendPacket(packetType) { /*...*/ }
/**
* This expects a specific packet type to be received in the future
* @param {*} packetType
*/
awaitPackage(packetType) {
return new Promise((resolve, reject) => {
this.awaitedPacketTypes[packetType] = {
resolve,
reject
};
});
}
/**
* This gets called for every packet from the network side and calls the correct resolver if something waits for this packet type
* @param {*} packet
*/
onIncomingPacket(packet) {
if(this.awaitedPacketTypes[packet.type]) {
this.awaitedPacketTypes[packet.type].resolve(packet);
this.awaitedPacketTypes[packet.type] = undefined;
} else {
/*...*/
}
}
}
Or to be more clear: Can I somehow recreate the resolve() callback function behavior of awaitPackage + onIncomingPacket?
有点? rust Future 只是“可以轮询准备就绪的东西”,它是一个比 JS promise 低得多的概念。
有些库声称提供 JS 风格的承诺,但大多数异步库可能提供一个类似的对象,但名称不同,例如在 Tokio 中,您可能想要一个 oneshot channel,这是一个可以发送单个值的通道,结果类似于:
struct Packet { r#type: &'static str }
struct Client {
awaited: Mutex<HashMap<&'static str, Sender<Packet>>>
}
impl Client {
async fn ping(&self) -> Packet {
self.send_packet("Pong").await;
self.await_package("Pong").await.unwrap()
}
async fn send_packet(&self, _: &'static str) {}
fn await_package(&self, packet_type: &'static str) -> Receiver<Packet> {
let (tx, rx) = channel();
self.awaited.lock().unwrap().insert(packet_type, tx);
rx
}
fn on_incoming_packet(&self, packet: Packet) {
if let Some(tx) = self.awaited.lock().unwrap().remove(packet.r#type) {
tx.send(packet);
}
}
}
目前我正在编写一个纯 Rust MQTT5 库(我知道那里有现有的库,但我更想学习 Rust)并且我偶然发现了这个问题。
我在 tokio 1.0.1 中使用最新的稳定 Rust。
当我通过网络发送一个数据包时,我经常期待服务器的响应(下面的示例 PingReq/PingAck、Ping/Pong)。
省略了很多有关超时和数据包冲突的逻辑,我在 JavaScript 中编写了一个简化版本的逻辑(因为我对此非常了解)。
这种逻辑将如何转化为 Rust 及其未来? 或者更清楚:我能以某种方式重新创建 awaitPackage + onIncomingPacket 的 resolve() 回调函数行为吗?
class Client {
awaitedPacketTypes = {};
/**
* a ping consist of a send ping and a receive pong
*/
async ping(){
await this.sendPacket("Ping");
return await this.awaitPackage("Pong");
}
async sendPacket(packetType) { /*...*/ }
/**
* This expects a specific packet type to be received in the future
* @param {*} packetType
*/
awaitPackage(packetType) {
return new Promise((resolve, reject) => {
this.awaitedPacketTypes[packetType] = {
resolve,
reject
};
});
}
/**
* This gets called for every packet from the network side and calls the correct resolver if something waits for this packet type
* @param {*} packet
*/
onIncomingPacket(packet) {
if(this.awaitedPacketTypes[packet.type]) {
this.awaitedPacketTypes[packet.type].resolve(packet);
this.awaitedPacketTypes[packet.type] = undefined;
} else {
/*...*/
}
}
}
Or to be more clear: Can I somehow recreate the resolve() callback function behavior of awaitPackage + onIncomingPacket?
有点? rust Future 只是“可以轮询准备就绪的东西”,它是一个比 JS promise 低得多的概念。
有些库声称提供 JS 风格的承诺,但大多数异步库可能提供一个类似的对象,但名称不同,例如在 Tokio 中,您可能想要一个 oneshot channel,这是一个可以发送单个值的通道,结果类似于:
struct Packet { r#type: &'static str }
struct Client {
awaited: Mutex<HashMap<&'static str, Sender<Packet>>>
}
impl Client {
async fn ping(&self) -> Packet {
self.send_packet("Pong").await;
self.await_package("Pong").await.unwrap()
}
async fn send_packet(&self, _: &'static str) {}
fn await_package(&self, packet_type: &'static str) -> Receiver<Packet> {
let (tx, rx) = channel();
self.awaited.lock().unwrap().insert(packet_type, tx);
rx
}
fn on_incoming_packet(&self, packet: Packet) {
if let Some(tx) = self.awaited.lock().unwrap().remove(packet.r#type) {
tx.send(packet);
}
}
}