Delay there added to make sure that coroutine is dispatched and printed message on first 2 iterations
Join is to make sure that coroutine is completed after cancellation, because cancel doesn’t suspend until actual coroutine is cancelled, it just sends a signal, this is why Job.cancelAndJoin exists, which just does cancel + join, same as in this examaple
Without join there is a chance that “I’m sleeping” will be printed after “Now I can quit”, though there is probably a low chance that it will happen with this code, but if you reduce timeouts to something like 1ms it may happen