Delay the evaluation of a paramless async function and cache the result. Adapted from mafintosh/thunky
Let's make a simple function that returns a random number 1 second after it is called for the first time
extern crate thunky;
extern crate rand;
use thunky::*;
use rand::Rng;
fn main () {
let run = move |thunk: &Thunky<u32, &str>| {
let mut rng = rand::thread_rng();
thunk.cache(Ok(rng.gen::<u32>()));
};
let thunk = Thunky::new(Box::new(run));
// I miss JavaScript's `setTimeout()`
let thunk_clone = Arc::clone(&thunk);
let when = Instant::now() + Duration::from_millis(1000);
let task = Delay::new(when)
.and_then(move |_| {
let mut rng = rand::thread_rng();
thunk_clone.cache(Ok(rng.gen::<u32>()));
Ok(())
})
.map_err(|e| panic!("delay errored; err={:?}", e));
thunk.run(Box::new(|arg: &Result<u32, &str>| -> () {
println!("{}", arg.unwrap()); // prints random number
}));
tokio::run(task);
thunk.run(Box::new(|arg: &Result<u32, &str>| -> () {
println!("{}", arg.unwrap()); // prints the same random number as above
}));
}
If the thunk cache function is called with an Err<E>
, it will not cache the result
let v = Mutex::new(0);
let run = move |thunk: &Thunky<u32, &str>| {
if *v.lock().unwrap() == 0 {
thunk.cache(Err("not cache"))
} else if *v.lock().unwrap() == 1 {
thunk.cache(Ok(100))
}
*v.lock().unwrap() += 1;
}
let thunk = Thunky::new(Box::new(run));
thunk.run(Box::new(|arg: &Result<u32, &str>| -> () {
assert_eq!("not cache", arg.unwrap_err());
}))
thunk.run(Box::new(|arg: &Result<u32, &str>| -> () {
assert_eq!(100, arg.unwrap());
}))
cargo add thunky