Concurrently call async method for all elements of a vector

I am working with wasm_bindgen and I have a Widget that is constructed by JS and does some work on a browser. This widget holds a Data struct that has several vectors with different types of resources needed for the work it does. Some of these resources need to be loaded asynchronously.

pub struct Widget {
  data: Data
}

pub struct Data {
  pub images: Vec<Image>
}

pub struct Image {
  pixels: Vec<u8>
}

impl Image {
  pub async fn load(&mut self) {
    let pixels = fetch("url").await.unwrap();

    self.pixels = pixels;
  }
}

Ideally, I want to have a function I can call from the JS side that loads all the images concurrently. Something like this:

impl Widget {
  pub fn load(&mut self) -> Promise {
    let loaders = self
            .data
            .images
            .iter_mut()
            .map(|image| image.load());

      future_to_promise(async move {
          join_all(loaders).await;

          Ok(JsValue::UNDEFINED)
      })
  }
}

However, I can't do that because the lifetime of the future is 'static and outlives self.data.images. This Github answer works around that by returning a Promise, assigning the data from self to a variable and moving that into an async block which is what I tried doing but I still have this problem.

I can't see any way around this though. Even if I create closures that can be moved into the async block, those closures will need to change the image structs, which are not 'static.

I'm a bit stuck and wouldn't mind getting some pointers. I don't mind spending some time on this so if you have any resources that could help me understand it better please let me know.
So far I took a look at the Async Book and the wasm_bindgen guide for promises and futures.

The iter_mut function is returning an iterator that holds a reference to self.data.images with the same lifetime as &mut self, and the iterator is getting moved into the future. So this is why it is not able to satisfy 'static. A simple way to solve it could be to make images an Rc<RefCell<Vec<Image>>>, and clone that into the future:

pub struct Data {
  pub images: Rc<RefCell<Vec<Image>>>
}
// ...
impl Widget {
  pub fn load(&mut self) -> Promise {
    let images = self.data.images.clone();

    future_to_promise(async move {
      let images = images.borrow_mut();
      let loaders = images.iter_mut().map(|image| image.load());
      join_all(loaders).await;

      Ok(JsValue::UNDEFINED)
    })
  }
}

Note this will not be re-entrant, you can use try_borrow_mut to handle the case where load might be called twice.

Ah, passing a smart pointer around so Rust knows the value will be kept alive and then mutating it through a RefCell. Thank you very much, this is what I was looking for!