Skip to content

Commit b44bd54

Browse files
committed
don't use errors as control flow
1 parent 4cdb7b0 commit b44bd54

File tree

1 file changed

+72
-72
lines changed

1 file changed

+72
-72
lines changed

dash-renderer/src/actions/index.js

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -136,48 +136,44 @@ function moveHistory(changeType) {
136136
}
137137

138138
function unwrapIfNotMulti(paths, idProps, spec, anyVals, depType) {
139+
let msg = '';
140+
139141
if (isMultiValued(spec)) {
140-
return idProps;
142+
return [idProps, msg];
141143
}
144+
142145
if (idProps.length !== 1) {
143146
if (!idProps.length) {
144-
if (typeof spec.id === 'string') {
145-
throw new ReferenceError(
146-
'A nonexistent object was used in an `' +
147-
depType +
148-
'` of a Dash callback. The id of this object is `' +
149-
spec.id +
150-
'` and the property is `' +
151-
spec.property +
152-
'`. The string ids in the current layout are: [' +
153-
keys(paths.strs).join(', ') +
154-
']'
155-
);
156-
}
157-
throw new ReferenceError(
147+
const isStr = typeof spec.id === 'string';
148+
msg =
158149
'A nonexistent object was used in an `' +
159-
depType +
160-
'` of a Dash callback. The id of this object is ' +
161-
JSON.stringify(spec.id) +
162-
(anyVals ? ' with MATCH values ' + anyVals : '') +
163-
' and the property is `' +
164-
spec.property +
165-
'`. The wildcard ids currently available are logged above.'
166-
);
167-
}
168-
throw new ReferenceError(
169-
'Multiple objects were found for an `' +
150+
depType +
151+
'` of a Dash callback. The id of this object is ' +
152+
(isStr
153+
? '`' + spec.id + '`'
154+
: JSON.stringify(spec.id) +
155+
(anyVals ? ' with MATCH values ' + anyVals : '')) +
156+
' and the property is `' +
157+
spec.property +
158+
(isStr
159+
? '`. The string ids in the current layout are: [' +
160+
keys(paths.strs).join(', ') +
161+
']'
162+
: '`. The wildcard ids currently available are logged above.');
163+
} else {
164+
msg =
165+
'Multiple objects were found for an `' +
170166
depType +
171167
'` of a callback that only takes one value. The id spec is ' +
172168
JSON.stringify(spec.id) +
173169
(anyVals ? ' with MATCH values ' + anyVals : '') +
174170
' and the property is `' +
175171
spec.property +
176172
'`. The objects we found are: ' +
177-
JSON.stringify(map(pick(['id', 'property']), idProps))
178-
);
173+
JSON.stringify(map(pick(['id', 'property']), idProps));
174+
}
179175
}
180-
return idProps[0];
176+
return [idProps[0], msg];
181177
}
182178

183179
function startCallbacks(callbacks) {
@@ -259,26 +255,30 @@ async function fireReadyCallbacks(dispatch, getState, callbacks) {
259255
return preventCallback();
260256
}
261257

262-
let outputs;
263-
try {
264-
outputs = allOutputs.map((out, i) =>
265-
unwrapIfNotMulti(
266-
paths,
267-
map(pick(['id', 'property']), out),
268-
cb.callback.outputs[i],
269-
cb.anyVals,
270-
'Output'
271-
)
258+
const outputs = [];
259+
const outputErrors = [];
260+
allOutputs.forEach((out, i) => {
261+
const [outi, erri] = unwrapIfNotMulti(
262+
paths,
263+
map(pick(['id', 'property']), out),
264+
cb.callback.outputs[i],
265+
cb.anyVals,
266+
'Output'
272267
);
273-
} catch (e) {
274-
if (e instanceof ReferenceError && !flatten(inVals).length) {
275-
// This case is all-empty multivalued wildcard inputs,
276-
// which we would normally fire the callback for, except
277-
// some outputs are missing. So instead we treat it like
278-
// regular missing inputs and just silently prevent it.
279-
return preventCallback();
268+
outputs.push(outi);
269+
if (erri) {
270+
outputErrors.push(erri);
280271
}
281-
throw e;
272+
});
273+
if (outputErrors.length) {
274+
if (flatten(inVals).length) {
275+
refErr(outputErrors, paths);
276+
}
277+
// This case is all-empty multivalued wildcard inputs,
278+
// which we would normally fire the callback for, except
279+
// some outputs are missing. So instead we treat it like
280+
// regular missing inputs and just silently prevent it.
281+
return preventCallback();
282282
}
283283

284284
payload = {
@@ -431,8 +431,8 @@ function fillVals(paths, layout, cb, specs, depType, allowAllMissing) {
431431
const errors = [];
432432
let emptyMultiValues = 0;
433433

434-
const fillInputs = (inputList, i) =>
435-
unwrapIfNotMulti(
434+
const inputVals = getter(paths).map((inputList, i) => {
435+
const [inputs, inputError] = unwrapIfNotMulti(
436436
paths,
437437
inputList.map(({id, property, path: path_}) => ({
438438
id,
@@ -443,44 +443,44 @@ function fillVals(paths, layout, cb, specs, depType, allowAllMissing) {
443443
cb.anyVals,
444444
depType
445445
);
446-
447-
const tryFill = (inputList, i) => {
448-
try {
449-
const inputs = fillInputs(inputList, i);
450-
if (isMultiValued(specs[i]) && !inputs.length) {
451-
emptyMultiValues++;
452-
}
453-
return inputs;
454-
} catch (e) {
455-
if (e instanceof ReferenceError) {
456-
errors.push(e);
457-
return null;
458-
}
459-
// any other error we still want to see!
460-
throw e;
446+
if (isMultiValued(specs[i]) && !inputs.length) {
447+
emptyMultiValues++;
461448
}
462-
};
463-
464-
const inputVals = getter(paths).map(allowAllMissing ? tryFill : fillInputs);
449+
if (inputError) {
450+
errors.push(inputError);
451+
}
452+
return inputs;
453+
});
465454

466455
if (errors.length) {
467-
if (errors.length + emptyMultiValues === inputVals.length) {
456+
if (
457+
allowAllMissing &&
458+
errors.length + emptyMultiValues === inputVals.length
459+
) {
468460
// We have at least one non-multivalued input, but all simple and
469461
// multi-valued inputs are missing.
470462
// (if all inputs are multivalued and all missing we still return
471463
// them as normal, and fire the callback.)
472464
return null;
473465
}
474466
// If we get here we have some missing and some present inputs.
475-
// That's a real error, so rethrow the first missing error.
467+
// Or all missing in a context that doesn't allow this.
468+
// That's a real problem, so throw the first message as an error.
469+
refErr(errors, paths);
470+
}
471+
472+
return inputVals;
473+
}
474+
475+
function refErr(errors, paths) {
476+
const err = errors[0];
477+
if (err.indexOf('logged above') !== -1) {
476478
// Wildcard reference errors mention a list of wildcard specs logged
477479
// TODO: unwrapped list of wildcard ids?
478480
// eslint-disable-next-line no-console
479481
console.error(paths.objs);
480-
throw errors[0];
481482
}
482-
483-
return inputVals;
483+
throw new ReferenceError(err);
484484
}
485485

486486
function handleServerside(config, payload, hooks) {

0 commit comments

Comments
 (0)