mudge/pacta — pull request #5 by rbelouin (2014-01-22 19:03:39+00:00)
Title: Some methods to work efficiently with rejected promises.

### mapError
```mapError```'s purpose is to apply the given function on the promise reason parameter if that promise is rejected.

N.B: it's far different from ```onRejected``` whose purpose is returning a ```fulfilled``` promise from a reason variable. ```mapError``` will still return a ```rejected``` promise if the initial promise was rejected.

Signature compared to existing methods:
```haskell
-- e and f are "failure" types
-- a and b are "success" types

mapError :: Promise e a -> (e -> f) -> Promise f a
map :: Promise e a -> (a -> b) -> Promise e b
onRejected :: Promise e a -> (e -> a) -> Promise e a
```

Example:
```javascript
var row = new Promise();
//row.resolve('{"message":"it works!"}');
row.reject('{"message":"there is an error"}');

var parsed = row.mapError(JSON.parse).map(JSON.parse);

var printed = parsed
.mapError(function(data) {
console.error(data.message);
})
.map(function(data) {
console.log(data.message);
});
```

### chainError
```chainError```'s purpose is quite similar to ```onRejected```'s one, but the way they are working is far different.
With ```onRejected```, you'll juste have to return a value to make the initial promise return a ```fulfilled``` promise, and you'll have to throw an exception if you want to make it return a ```rejected``` one.
```chainError```'s approach is more functional, and the promise you'll get by calling this method is the one returned by the callback you give to it.

Signature compared to existing methods:
```haskell
-- e and f are "failure" types
-- a and b are "success" types

chainError :: Promise e a -> (e -> Promise f a) -> Promise f a
chain :: Promise e a -> (a -> Promise e b) -> Promise e b
onRejected :: Promise e a -> (e -> a) -> Promise e a
```

Example:
```javascript
var criticalAjaxCallThatMayFail = function() {
var p = new Promise();

setTimeout(function() {
if(Date.now() % 2 == 0) {
p.reject("Request timed out");
}
else {
p.resolve("This is a critical sentence.");
}
}, 2000);

return p;
};

var getMessage = function(error) {
if(error) {
console.error("Error received: " + error);
console.log("Retrying…");
}

console.log("Sending request…");
return criticalAjaxCallThatMayFail();
};

/* Retry 3 times if it fails */
getMessage()
.chainError(getMessage)
.chainError(getMessage)
.map(console.log)
.mapError(console.error);
```

### map and chain
From now, these methods won't return a "forever pending" promise if you call it on a rejected promise.
See previous examples.

```javascript
var p = new Promise();
p.reject("error");

var p2 = p.map(function(x) { return x + 1; });
setTimeout(function() {
console.log(p2.state()); // printed "pending", but "rejected" from now
}, 100);
```