; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
const verror_1 = require("verror"); | |
const format_verror_1 = require("./format-verror"); | |
/** | |
* Accumulates multiple errors, to all be thrown together instead of one at a time. | |
*/ | |
class ErrorBuffer { | |
constructor() { | |
this.errors = []; | |
} | |
/** | |
* Adds the given error(s) (or other objects, which are converted to errors). | |
*/ | |
add(...errors) { | |
for (let error of errors) { | |
if (error instanceof verror_1.MultiError) | |
this.add(...error.errors()); | |
else { | |
if (!(error instanceof Error)) | |
error = new Error(String(error)); | |
else if (this.errors.indexOf(error) !== -1) { | |
/* Deduplicate errors. | |
* | |
* Consider this scenario: | |
* 1. Promise A is started. | |
* 2. Promise B is started. It awaits the result of A. | |
* 3. Promise C is started. It also awaits the result of A. | |
* 4. PromiseEach is called, to collect the results of promises B and C. | |
* 5. Promise A rejects with error E. | |
* 6. Promise B, previously waiting on A, rejects with E. | |
* 7. Promise C, previously waiting on A, also rejects with E. | |
* 8. PromiseEach collects the results of [B, C]. They are { B: rejection(E), C: rejection(E) }. | |
* 9. PromiseEach finds that B rejected with E, so it adds E to its ErrorBuffer. | |
* 10. PromiseEach finds that C rejected with E, so it adds E to its ErrorBuffer. | |
* 11. PromiseEach rejects with [E, E]. | |
* | |
* But, if ErrorBuffer deduplicates the errors it receives, then step 10 has no effect, because E is already in the ErrorBuffer. As a result, in step 11, PromiseEach rejects with E instead of [E, E]. | |
* | |
* Note that this deduplication only applies to instances of Error. When other values are passed in, they are converted to a new instance of Error each time, so there is no chance to deduplicate them. | |
*/ | |
continue; | |
} | |
this.errors.push(error); | |
} | |
} | |
} | |
/** | |
* Adds the given error, then throws it. If other errors have been added already, throws a `MultiError` instead. | |
*/ | |
throw(error) { | |
const throwSingle = !this.errors.length; | |
this.add(error); | |
throw throwSingle ? error : format_verror_1.PrettyVError.errorFromList(this.errors); | |
} | |
/** | |
* Catches errors thrown from the given function, adding them to the array of accumulated errors. | |
*/ | |
catching(fun) { | |
try { | |
return fun(); | |
} | |
catch (e) { | |
this.add(e); | |
} | |
} | |
/** | |
* Catches errors thrown from the given async function or promise, adding them to the array of accumulated errors. | |
*/ | |
async catchingAsync(fun) { | |
try { | |
if (typeof fun === "function") | |
return await fun(); | |
else | |
return await fun; | |
} | |
catch (e) { | |
this.add(e); | |
} | |
} | |
/** | |
* Throws any accumulated errors. | |
*/ | |
check() { | |
const error = format_verror_1.PrettyVError.errorFromList(this.errors); | |
if (error) | |
throw error; | |
} | |
get isEmpty() { | |
return !this.errors.length; | |
} | |
} | |
exports.ErrorBuffer = ErrorBuffer; | |
//# sourceMappingURL=errors.js.map |