rust 中的语法await!正式改成.await, 关于Future这套东东,很有必要了解。象actix-web也已经1.0了,里面其实也是到处Future这套。async、await这套东东,是rust的硬知识。
一、async和await的几种形式
“async和其他Future是懒惰的:它们在运行之前什么都不做。运行Future的最常见方式是.await它。当在Future上调用.await时,它将尝试运行以完成它。如果Future被阻止,它将让出当前线程。当可以取得更多进展时,执行者将获取 Future并将继续运行,以便.await解决。”
1、async
(1)async fn
当然,也有很多情况,比如函数中有.await; 也可能没有.await的不同情况。这种也会导致,返回值也完全不一样。
比如,
async fn compute(){
println!("async->");
}
这个相当于:[只是相当于]
fn compute()->impl Future<Output = ()>{
println!("async->");
}
(2)async 和async move
async {}后直接一个代码块。没有取环境变量的所有权。
“async move块将获取它引用变量的所有权,允许它活得比目前的范围长,但放弃了与其他代码分享那些变量的能力”。
比如:
fn compute_01() -> impl Future<Output =Result<(),String>>{
async move{
for i in 1..10000{
let _ = i*2;
}
println!("=>01 it is over!");
Ok(())
}
}
(3)async闭包
fn compute_05(value:i32)->impl Future<Output=i32>{
let closure = async move |v:i32|{
compute_03().await;
v+1
};
closure(value)
}
一个综合的例子:
sync fn hello(){
println!("hello!");
// async fn
async fn world(){
println!("world!");
}
world().await;
// async block
let a = async{
println!("{:?}","hello world!");
};
a.await;
// async move block
let code ="shang hai".to_string();
let mut hp = HashMap::new();
hp.insert("code","600036");
let b = async move{
println!("hello world, i love {:?}",hp);
};
//println!("code:{:?}",hp); //error if uncommented
b.await;
}
2 、await
async并不必然就需要用await,但设计的初衷是想等.await调用。
在.await的调用上,需要注意两个方面,一方面是,什么情况下能用上.await;另一方面是, 用上.await函数本身有什么要求?
相当于,一个是从逻辑实质上的要求;另一个是外在形式上的要求;
(1)能用await的情况
await的用法很简单,一般主要有以下两个这中的一个条件,一种是显示的;一种是隐式的;
A、显示方式:调用的函数中与async相对应的安排的;比如,async; async move;
这种情况好理解,不详述。
B、隐式方式:没有明显的async相对应的安排,但函数的返回值实现了Future trait.
这种情况,是一种隐式的情况。比如,
struct data{
price :Vec<f64>
}
fn get_data(length: i64) ->data{
}
//但data 实现了Future trait, 即
impl Future for data{
// 省略......
}
//即实现的函数,有Poll<Self::Output>
(2)await有用时,函数体外面是一定有async这个壳套着的;
也就是说,只有函数的签名中有async,才允许用.await的;
async fn v(){
m().await // .await 是因为v()外面的签名,一定有一个async.
}
另外,说明一下,当函数的返回值形式实现了impl Future<Output =Result<>>类型时,可以用.await?的形式。
3、block_on()
另外,提一下block_on(). 如果没有这个函数,所有的异步相当于“箭射出后,但收不回来”。
block_on() 相当于让这个异步安排强制完成。
二、实例
1、相关说明
(1)#![feature(async_await)]
有时,会更长一些,比如
#![feature(async_await, await_macro, futures_api)],具体来说,
async_await 增加了对 async fn 语法的支持。
await_macro 增加了对 await! 宏的支持。
futures_api 增加了对 nightly std::future 和 std::task 模块的支持,这些模块定义了核心Future特征和依赖类型。
(2)并在nightly的环境中
2、代码
#![feature(async_await)]
use std::thread;
use std::time::Duration;
use futures::{Future};
use futures::executor::block_on;
fn compute_01() -> impl Future<Output =Result<(),String>>{
async move{
for i in 1..10000{
let _ = i*2;
}
println!("=>01 it is over!");
Ok(())
}
}
async fn compute_02(){
println!("=>02 is entering....");
compute_01().await;
//compute_04().await;
println!("=>02 is over!");
}
async fn compute_03(){
println!("=>03 is entering....");
for i in 1..10000{
let _ = i*2;
}
println!("=>03 it is over!");
}
fn compute_04(){
println!("=> 04 is entering....")
}
fn compute_05(value:i32)->impl Future<Output=i32>{
let closure = async move |v:i32|{
compute_03().await;
v+1
};
closure(value)
}
fn main() {
block_on(compute_02());
//compute_03();
block_on(compute_03());//必须把这些异步跑完
let val = block_on(compute_05(6));
println!("val :{:?}",val);
println!("hello world!");
thread::sleep(Duration::from_millis(500000));
}
三、输出结果
=>02 is entering....
=>01 it is over!
=>02 is over!
=>03 is entering....
=>03 it is over!
=>03 is entering....
=>03 it is over!
val :7
hello world!