Factor progress handling into another internal promise object

This makes progress events use the same machinery as fulfill and reject events. Spawned from #102.