"use strict";
|
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
|