cleanup callback hell with async