By nonblocking (no delay) I mean you have to find a way to delay (or not do anything) based on time.
That means one of 2 things, either you do your tasks based on time (a counter) or you do it with an ISR.
The first option works like you take action at intervals.
Or timestamped as Grumpy said.
Timeslice your main loop by checking events.
Either something received or time lapsed.
Don't block it by waiting.
If it's not time to do something, go ahead and do something else.
If you block your code by using a delay it cant check or do multiple tasks.
It's sort of multitasking, do all at once.