Comparing version
13
API.md
@@ -7,3 +7,3 @@ #API Reference | ||
- [`.catch(Function handler)`](#catchfunction-handler---promise) | ||
- [`.catch([Function ErrorClass...], Function handler)`](#catchfunction-errorclass-function-handler---promise) | ||
- [`.catch([Function ErrorClass|Function predicate...], Function handler)`](#catchfunction-errorclass-function-handler---promise) | ||
- [`.finally(Function handler)`](#finallyfunction-handler---promise) | ||
@@ -147,6 +147,15 @@ - [`.bind(dynamic thisArg)`](#binddynamic-thisarg---promise) | ||
#####`.catch([Function ErrorClass...], Function handler)` -> `Promise` | ||
#####`.catch([Function ErrorClass|Function predicate...], Function handler)` -> `Promise` | ||
This extends `.catch` to work more like catch-clauses in languages like Java or C#. Instead of manually checking `instanceof` or `.name === "SomeError"`, you may specify a number of error constructors which are eligible for this catch handler. The catch handler that is first met that has eligible constructors specified, is the one that will be called. | ||
This method also supports predicate-based filters. If you pass a | ||
predicate function instead of an error constructor, the predicate will receive | ||
the error as an argument. The return result of the predicate will be used | ||
determine whether the error handler should be called. | ||
Predicates should allow for very fine grained control over caught errors: | ||
pattern matching, error-type sets with set operations and many other techniques | ||
can be implemented on top of them. | ||
Example: | ||
@@ -153,0 +162,0 @@ |
@@ -28,16 +28,35 @@ /** | ||
function CatchFilter( instances, callback, boundTo ) { | ||
function CatchFilter( instances, callback, promise ) { | ||
this._instances = instances; | ||
this._callback = callback; | ||
this._boundTo = boundTo; | ||
this._promise = promise; | ||
} | ||
function safePredicate( predicate, e ) { | ||
var safeObject = {}; | ||
var retfilter = tryCatch1( predicate, safeObject, e ); | ||
if( retfilter === errorObj ) return retfilter; | ||
var safeKeys = Object.keys(safeObject); | ||
if( safeKeys.length ) { | ||
errorObj.e = new TypeError( | ||
"Catch filter must inherit from Error " | ||
+ "or be a simple predicate function" ); | ||
return errorObj; | ||
} | ||
return retfilter; | ||
} | ||
CatchFilter.prototype.doFilter = function CatchFilter$doFilter( e ) { | ||
if( e === null || typeof e !== "object" ) { | ||
throw e; | ||
} | ||
var cb = this._callback; | ||
for( var i = 0, len = this._instances.length; i < len; ++i ) { | ||
var item = this._instances[i]; | ||
if( e instanceof item ) { | ||
var ret = tryCatch1( cb, this._boundTo, e ); | ||
var itemIsErrorType = item === Error || | ||
( item != null && item.prototype instanceof Error ); | ||
if( itemIsErrorType && e instanceof item ) { | ||
var ret = tryCatch1( cb, this._promise._boundTo, e ); | ||
if( ret === errorObj ) { | ||
@@ -47,2 +66,15 @@ throw ret.e; | ||
return ret; | ||
} else if( typeof item === "function" && !itemIsErrorType ) { | ||
var shouldHandle = safePredicate(item, e); | ||
if( shouldHandle === errorObj ) { | ||
this._promise._attachExtraTrace( errorObj.e ); | ||
e = errorObj.e; | ||
break; | ||
} else if(shouldHandle) { | ||
var ret = tryCatch1( cb, this._promise._boundTo, e ); | ||
if( ret === errorObj ) { | ||
throw ret.e; | ||
} | ||
return ret; | ||
} | ||
} | ||
@@ -54,2 +86,2 @@ } | ||
module.exports = CatchFilter; | ||
module.exports = CatchFilter; |
@@ -100,5 +100,3 @@ /** | ||
var item = arguments[i]; | ||
if( typeof item === "function" && | ||
( item.prototype instanceof Error || | ||
item === Error ) ) { | ||
if( typeof item === "function" ) { | ||
catchInstances[j++] = item; | ||
@@ -109,3 +107,4 @@ } | ||
new TypeError( | ||
"A catch filter must be an error constructor"); | ||
"A catch filter must be an error constructor " | ||
+ "or a filter function"); | ||
@@ -119,3 +118,3 @@ this._attachExtraTrace( catchFilterTypeError ); | ||
fn = arguments[i]; | ||
var catchFilter = new CatchFilter( catchInstances, fn, this._boundTo ); | ||
var catchFilter = new CatchFilter( catchInstances, fn, this ); | ||
return this._then( void 0, catchFilter.doFilter, void 0, | ||
@@ -122,0 +121,0 @@ catchFilter, void 0, this.caught ); |
@@ -28,16 +28,35 @@ /** | ||
function CatchFilter( instances, callback, boundTo ) { | ||
function CatchFilter( instances, callback, promise ) { | ||
this._instances = instances; | ||
this._callback = callback; | ||
this._boundTo = boundTo; | ||
this._promise = promise; | ||
} | ||
function safePredicate( predicate, e ) { | ||
var safeObject = {}; | ||
var retfilter = tryCatch1( predicate, safeObject, e ); | ||
if( retfilter === errorObj ) return retfilter; | ||
var safeKeys = Object.keys(safeObject); | ||
if( safeKeys.length ) { | ||
errorObj.e = new TypeError( | ||
"Catch filter must inherit from Error " | ||
+ "or be a simple predicate function" ); | ||
return errorObj; | ||
} | ||
return retfilter; | ||
} | ||
CatchFilter.prototype.doFilter = function CatchFilter$doFilter( e ) { | ||
if( e === null || typeof e !== "object" ) { | ||
throw e; | ||
} | ||
var cb = this._callback; | ||
for( var i = 0, len = this._instances.length; i < len; ++i ) { | ||
var item = this._instances[i]; | ||
if( e instanceof item ) { | ||
var ret = tryCatch1( cb, this._boundTo, e ); | ||
var itemIsErrorType = item === Error || | ||
( item != null && item.prototype instanceof Error ); | ||
if( itemIsErrorType && e instanceof item ) { | ||
var ret = tryCatch1( cb, this._promise._boundTo, e ); | ||
if( ret === errorObj ) { | ||
@@ -47,2 +66,15 @@ throw ret.e; | ||
return ret; | ||
} else if( typeof item === "function" && !itemIsErrorType ) { | ||
var shouldHandle = safePredicate(item, e); | ||
if( shouldHandle === errorObj ) { | ||
this._promise._attachExtraTrace( errorObj.e ); | ||
e = errorObj.e; | ||
break; | ||
} else if(shouldHandle) { | ||
var ret = tryCatch1( cb, this._promise._boundTo, e ); | ||
if( ret === errorObj ) { | ||
throw ret.e; | ||
} | ||
return ret; | ||
} | ||
} | ||
@@ -54,2 +86,2 @@ } | ||
module.exports = CatchFilter; | ||
module.exports = CatchFilter; |
@@ -100,5 +100,3 @@ /** | ||
var item = arguments[i]; | ||
if( typeof item === "function" && | ||
( item.prototype instanceof Error || | ||
item === Error ) ) { | ||
if( typeof item === "function" ) { | ||
catchInstances[j++] = item; | ||
@@ -109,3 +107,4 @@ } | ||
new TypeError( | ||
"A catch filter must be an error constructor"); | ||
"A catch filter must be an error constructor " | ||
+ "or a filter function"); | ||
@@ -119,3 +118,3 @@ this._attachExtraTrace( catchFilterTypeError ); | ||
fn = arguments[i]; | ||
var catchFilter = new CatchFilter( catchInstances, fn, this._boundTo ); | ||
var catchFilter = new CatchFilter( catchInstances, fn, this ); | ||
return this._then( void 0, catchFilter.doFilter, void 0, | ||
@@ -122,0 +121,0 @@ catchFilter, void 0, this.caught ); |
{ | ||
"name": "bluebird", | ||
"description": "Full featured Promises/A+ implementation with exceptionally good performance", | ||
"version": "0.9.9-0", | ||
"version": "0.9.10-0", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "promise", |
@@ -320,2 +320,12 @@ [](https://travis-ci.org/petkaantonov/bluebird) | ||
Finally, Bluebird also supports predicate-based filters. If you pass a | ||
predicate function instead of an error type, the predicate will receive | ||
the error as an argument. The return result will be used determine whether | ||
the error handler should be called. | ||
Predicates should allow for very fine grained control over caught errors: | ||
pattern matching, error typesets with set operations and many other techniques | ||
can be implemented on top of them. | ||
See [API documentation for `.error()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#error-rejectedhandler----promise) | ||
@@ -322,0 +332,0 @@ |
437177
0.69%9096
0.55%677
1.5%