waitFor repeatedly runs a callback until it stops throwing or the timeout is reached, which helps with async state changes.