Propagate exceptions directly via the AsyncResult rather than raise

This makes writing async code much more natural, otherwise you'd have to do:

```python
def completion(result):
  try:
     result.get()
  except <everything>:
     self.client.add_listener(...)

try:
  self.client.operation_async(...).rawlink(completion)
except <everything>:
  self.client.add_listener(...)
```

when really the client operation should always return immediately and the exception handling logic should be consolidated in the async completions.