I'm not sure if I understand your problem right. A transmitting UART doesn't care if the receiver takes the data or not - the transmitter simply transmits the data if available. The only way to signal a transmitter to stop/continue transmission is using handshake (soft- or hardware).
The above is valid for a "real" COM port implementation, just as a basic description.
You wrote about the UsbUART. Here, things are a bit more complicated. The UsbUART tries to make a virtual COM port over an interface with a totally different approach. The USB functions must be blocking, because USB communication is always initiated by the host. On a real COM port, there's no real host - both transmitters may send at any time.
So, the USB host coordinates the communication, and to ensure that the previous data to send has been collected, the USB functions must be blocking.
Additionally, your approach of introducing a delay(!) would make the whole system slow, because the delay() function is simply a loop, which blocks the MCU for any other things (the same seems to apply to the original while-loop, I assume that's why the API states that CDCIsReady() function should be called prior to USBUART_PutString() function. The while-loop itself seems to be a fallback if CDCIsReady() has not been called.
So, I want to suggest the following: use the CDCIsReady() function to check if the last packet has been transmitted. If not (no space for a new packet), then decrement a local timeout variable (preferrably in a non-blocking way), and when the timeout expires, cancel any future communication - the actual packet can be kept IMHO, this enables you to detect if a terminal application has been started, so you can continue communication.