move state transition to precede callback invocations
add `join`