What I usually do is:
1) Determine if I am looking for an object to Exist/Be Visible/Be VisibleOnScreen/Disappear to mark as a success condition for my test step. (It can be anything depending on what you're trying to do)
2) Determine the maximum time for which I will wait after which I will mark the test step as failed e.g. If the successful login message does not show up for 60 seconds, my test step has failed
3) Arbitrarily choose a smaller time block that APPROXIMATES (no right or wrong answer, just pick something you feel will work) the minimum time the object Exists/is visible/changes state etc. e.g. I find that usually the successful login message appears within 5 seconds. So I pick 5 seconds.
4) Then I implement a counter that loops over this delay enough number of times to equal or match the maximum wait time I decided. Here is an example of code:
maxwait_time = 60000 ' in milliseconds
delayblock_time = 5000 'in milliseconds
count = (maxwait_time/delayblock_time) + 1
DO WHILE count>0
object_found = Sys.browser.page_home.WaitChild("msg_successfulLogin",100).Exists
IF object_found THEN
Log.Message("Object found")
'Do something
EXIT DO
ELSE
count = count - 1
AqUtils.Delay(delayblock_time)
END IF
LOOP
So what this essentially does is, wait in smaller increments to possibly end waiting as soon as the success condition is encountered, else wait till the maximum time and mark it as failed.