Handling Errors in the Future

Until now, we have conveniently ignored the question of how to handle exceptions. What happens if our POST to the back end results in a 400-class error? How can we design Hipster MVC so that developers can handle exceptions appropriately?

Had we stuck with options, the answer would have been to add yet another callback inside the Map of options. Luckily for us, Completer and Future have a formal mechanism for dealing with just such a situation. A Completer invokes completeError to signal a problem and Future deals with problems with handleException to do something with that exception.

The default data sync behavior in HipsterSync would signal an exceptional condition to the future by calling completeError when the request status is not okay (for example, greater than 299).

 
class​ HipsterSync {
 
// ...
 
static​ Future _defaultSync(method, model) {
 
var​ request = ​new​ HttpRequest(),
 
completer = ​new​ Completer();
 
request.
 
onLoad.
 
listen((event) {
 
var​ req = event.target;
 
if​ (req.status > 299) {
 
completer.
 
completeError(​"That ain't gonna work: ${req.status}"​);
 
}
 
 
else​ {
 
var​ json = JSON.decode(req.responseText);
 
completer.complete(json);
 
}
 
});
 
// Open and send the request
 
return​ completer.future;
 
}
 
}

The value in completeError does not have to be a subclass of Exception—any old object will do. In this case, we supply a simple string.

 
if​ (req.status > 299) {
 
completer.
 
completeError(​"That ain't gonna work: ${req.status}"​);
 
}

Back in the model class, we need to handle this exceptional case. The then method returns void, so it is not chainable. This requires us to store the after-send Future back in HipsterModel.save() in a local variable. We can then inject a happy-path then behavior into the Future along with handleException behavior.

 
class​ HipsterModel {
 
// ...
 
Future<HipsterModel> save() {
 
Completer completer = ​new​ Completer();
 
Future after_send = HipsterSync.send(​'post'​, ​this​);
 
 
after_send.
 
then((attrs) { ​/* ... */​ });
 
 
after_send.
 
handleException((e) { ​/* ... */​ });
 
return​ completer.future;
 
}
 
}

Since HipsterModel#save() is itself a Future, it should handle exceptions with a completeError of its own.

 
after_send.
 
handleException((e) {
 
completer.completeError(e);
 
return​ true;
 
});
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.27.72