异步关闭时出错:生存期可能不够长



我是个新手,刚开始尝试构建一个discordbot,我得到了这个thread_local!()全局变量thread_local!(static USER_DATA: RefCell<HashMap<u64, String>> = RefCell::new(HashMap::new()));和我在尝试使用异步闭包访问变量时出错,如下所示,异步闭包位于函数中

USER_DATA.with(|data| async {
if data.borrow().contains_key(msg.author.id.as_u64()) {
let binusmaya_api = BinusmayaAPI{token: data.borrow().get(msg.author.id.as_u64()).unwrap().clone()};
let schedule: String = binusmaya_api.get_schedule().await.expect("something's wrong");
msg.channel_id.send_message(&ctx.http, |m| {
m.embed(|e| e
.colour(0x03aaf9)
.field("Schedule", schedule, false)
)
}).await.unwrap();
} else {
msg.channel_id.send_message(&ctx.http, |m| {
m.embed(|e| e
.colour(0x03aaf9)
.field("You're not registered", "please register first using `=register` command", false)
)
}).await.unwrap();
}
});

这是的错误日志

error: lifetime may not live long enough
--> src/discord.rs:240:24
|
240 |       USER_DATA.with(|data| async {
|  _____________________-----_^
| |                     |   |
| |                     |   return type of closure `impl std::future::Future` contains a lifetime `'2`
| |                     has type `&'1 RefCell<HashMap<u64, std::string::String>>`
241 | |         if data.borrow().contains_key(msg.author.id.as_u64()) {
242 | |             let binusmaya_api = BinusmayaAPI{token: data.borrow().get(msg.author.id.as_u64()).unwrap().clone()};
243 | |             let schedule: String = binusmaya_api.get_schedule().await.expect("something's wrong");
...   |
257 | |         }
258 | |     });
| |_____^ returning this value requires that `'1` must outlive `'2`
error: could not compile `BINUSMAYA_Discord_Bot` due to previous error

我不知道如何解决这个问题,因为我不能自由更改生存期,我应该改为声明全局变量的方式吗?我不想做不安全的方式,这就是为什么我使用thread_local!()

.with()方法是同步的(文档中没有提到async或Future(。所以它期望一个同步块。在内部使用async/await似乎是错误的。

可以先复制出这样的令牌:

let token_opt: Option<String> = USER_DATA.with(|data| {
data.borrow().get(msg.author.id.as_u64()).clone()
});

注意,.get()已经返回了一个Option,所以它在里面保存了一个额外的if

然后在异步代码中使用token_opt

match token_opt {
Some(token) => {
let binusmaya_api = BinusmayaAPI{token: token};
let schedule: String = binusmaya_api.get_schedule().await.expect("something's wrong");
msg.channel_id.send_message(&ctx.http, |m| {
m.embed(|e| e
.colour(0x03aaf9)
.field("Schedule", schedule, false)
)
}).await.unwrap();
}
None => {
msg.channel_id.send_message(&ctx.http, |m| {
m.embed(|e| e
.colour(0x03aaf9)
.field("You're not registered", "please register first using `=register` command", false)
)
}).await.unwrap();
}
}

请注意,thread_local意味着每个线程都创建自己的USER_DATA副本,因此,如果此代码是从多个线程运行的,则某些线程将不会有令牌,除非您在使用同一线程之前添加了令牌。

最新更新