updated: async (added timeout)