How do I wrap EventTarget.addEventListener() so it can be used as an async iterator?

How does one use async iterators to consume events coming from a callback, like EventTarget.addEventListener and similar?

As an example, the following code does not exist but illustrates what I’d like to see:

for await (const event of onevent('scroll')) {
  console.log(event)
  break // cleanup
}

When attempting to create this onevent wrapper function, I run into basic issues – like yield not being available in the callback (makes sense) and no obvious way to remove listeners from when the listener breaks a loop.

async function *onevent(eventName) {
  const changeEvent = (event) => {
    yield event // yield cannot be used in this scope
  }

   window.addEventListener(eventName, changeEvent)

   // There doesn't seem to be a way to cleanup on loop "break"
   // window.removeEventListener(eventName, changeEvent)
}

for await (const event of onevent('scroll')) {
  console.log(event)
  break // cleanup?
}

Or am I misunderstanding the purpose of async iterators?