From e8f634bcb3dbef05e79e5ae7667db7de49a9d886 Mon Sep 17 00:00:00 2001 From: Max Fierke <max@maxfierke.com> Date: Sat, 18 Sep 2021 21:18:28 -0500 Subject: [PATCH] Add onError parameter to perform helper Allows setting to reporting function for reporting to error handlers, etc. Also allows setting to null to swallow all errors --- addon/helpers/perform.js | 32 +++++++++++- tests/integration/helpers/perform-test.js | 62 +++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/addon/helpers/perform.js b/addon/helpers/perform.js index b144a57df..86a140e72 100644 --- a/addon/helpers/perform.js +++ b/addon/helpers/perform.js @@ -1,8 +1,38 @@ import { helper } from '@ember/component/helper'; +import { assert } from '@ember/debug'; import { taskHelperClosure } from 'ember-concurrency/-private/helpers'; +function maybeReportError(onError) { + return function (e) { + if (typeof onError === 'function') { + onError(e); + } else if (onError === null) { + // Do nothing + } else { + assert( + `The onError argument passed to the \`perform\` helper should be a function or null; you passed ${onError}`, + false + ); + } + }; +} + export function performHelper(args, hash) { - return taskHelperClosure('perform', 'perform', args, hash); + let perform = taskHelperClosure('perform', 'perform', args, hash); + + if (hash && typeof hash.onError !== 'undefined') { + return function (...innerArgs) { + try { + let taskInstance = perform(...innerArgs); + return taskInstance.catch(maybeReportError(hash.onError)); + // eslint-disable-next-line no-empty + } catch { + maybeReportError(hash.onError); + } + }; + } else { + return perform; + } } export default helper(performHelper); diff --git a/tests/integration/helpers/perform-test.js b/tests/integration/helpers/perform-test.js index e3d29900d..7c6c49776 100644 --- a/tests/integration/helpers/perform-test.js +++ b/tests/integration/helpers/perform-test.js @@ -35,4 +35,66 @@ module('Integration | helpers | perform', function (hooks) { assert.ok(true); }); + + test('can pass onError=null to have it swallow errors thrown from task', async function (assert) { + assert.expect(1); + + this.owner.register( + 'component:test-swallow-error', + Component.extend({ + errorGeneratingTask: task(function* () { + throw new Error('You should not see me!'); + }), + }) + ); + + this.owner.register( + 'template:components/test-swallow-error', + hbs` + <button {{on 'click' (perform this.errorGeneratingTask onError=null)}}> + I create an error! + </button> + ` + ); + + await render(hbs`<TestSwallowError />`); + + await click('button'); + + assert.ok(true); + }); + + test('can pass onError=someFn to have it call someFn(e)', async function (assert) { + assert.expect(2); + + let error = null; + + this.owner.register( + 'component:test-swallow-error', + Component.extend({ + errorGeneratingTask: task(function* () { + throw new Error('You should not see me!'); + }), + errorReport(e) { + error = e; + }, + }) + ); + + this.owner.register( + 'template:components/test-swallow-error', + hbs` + <button {{on 'click' (perform this.errorGeneratingTask onError=this.errorReport)}}> + I create an error! + </button> + ` + ); + + await render(hbs`<TestSwallowError />`); + + await click('button'); + + assert.ok(true); + assert.ok(error instanceof Error); + }); });