Skip to content

Commit

Permalink
fix: do not return a rejected promise; throw it instead. (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
Federkun committed Jun 27, 2021
1 parent 0e7c5d2 commit 819f9ca
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 17 deletions.
25 changes: 25 additions & 0 deletions src/use-async-effect.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,31 @@ it("does throw promise rejections", async (done) => {
render(<TestComponent />);
});

it("does throw promise rejections in loops", async (done) => {
const TestComponent: React.FC = () => {
useAsyncEffect(function* () {
const value1 = yield Promise.resolve('foobar')
expect(value1).toEqual('foobar');

for(let i=0; i<=3; i++) {
try {
yield Promise.reject(new Error("Something went wrong."));
done.fail("Should throw");
} catch (err) {
expect(err.message).toEqual("Something went wrong.");
}
}

const value2 = yield Promise.resolve('hello')
expect(value2).toEqual('hello');

done();
}, []);
return null;
};
render(<TestComponent />);
});

it("logs error about uncaught promises to the console", async (done) => {
const TestComponent: React.FC = () => {
useAsyncEffect(function* () {
Expand Down
41 changes: 24 additions & 17 deletions src/use-async-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,37 @@ export const useAsyncEffect = (
const run = async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let result: IteratorResult<any> = { value: undefined, done: false };
let lastError: Error | undefined = undefined;

do {
result = generator.next(result.value);
if (result.value && result.value.then) {
try {
result.value = await result.value;
} catch (err) {
if (isCanceled) {
onCancelError(err);
return;
}
try {
result = !lastError
? generator.next(result.value)
: generator.throw(lastError);
lastError = undefined;

if (result.value && result.value.then) {
try {
generator.throw(err);
result.value = await result.value;
} catch (err) {
console.error(`[use-async-effect] Unhandled promise rejection.`);
console.error(err);
return;
if (isCanceled) {
onCancelError(err);
return;
}

lastError = err;
}
}
}
if (isCanceled) {
if (isCanceled) {
return;
}
onCancel = noop;
onCancelError = noop;
} catch (err) {
console.error(`[use-async-effect] Unhandled promise rejection.`);
console.error(err);
return;
}
onCancel = noop;
onCancelError = noop;
} while (result.done === false);
if (result.value) {
cleanupHandler = result.value;
Expand Down

0 comments on commit 819f9ca

Please sign in to comment.