From c10d5cf115535bce9a91612ab8bc66e487186990 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Tue, 17 Sep 2019 00:08:43 +0700 Subject: [PATCH] Fix a bug with Promise.catch() in PromiseMiddleware The pending action will be modified and a newly created promise handler will be returned. This has (suddenly?) caused errors in tests because the catch() handlers defined in tests would be called before the one defined in PromiseMiddleware: const p = new Promise(...) const {payload} = store.dispatch({ payload: new Promise(...), type: '...', }) try { await payload } catch (err) { // this handler would be invoked before the catch handler in // PromiseMiddleware } since the PromiseMiddleware adds a then-callback, followed by a catch-callback. --- packages/jsonrpc/src/redux.test.ts | 1 + .../redux/src/middleware/PromiseMiddleware.ts | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/jsonrpc/src/redux.test.ts b/packages/jsonrpc/src/redux.test.ts index 33d66bf..1938208 100644 --- a/packages/jsonrpc/src/redux.test.ts +++ b/packages/jsonrpc/src/redux.test.ts @@ -225,6 +225,7 @@ describe('createActions', () => { error = err } expect(error!).toBeTruthy() + expect(store.getState().mapping.error).toMatch(/status code 500/) expect(store.getState().handler.error).toMatch(/status code 500/) }) }) diff --git a/packages/redux/src/middleware/PromiseMiddleware.ts b/packages/redux/src/middleware/PromiseMiddleware.ts index e14dc98..d8c5d9f 100644 --- a/packages/redux/src/middleware/PromiseMiddleware.ts +++ b/packages/redux/src/middleware/PromiseMiddleware.ts @@ -24,21 +24,26 @@ export class PromiseMiddleware { if (!isPromise(payload)) { return next(action) } - const pendingAction = { - ...action, - status: 'pending', - } - // Propagate this action. Only attach listeners to the promise. - next(pendingAction) - payload + const promise = payload .then(result => { store.dispatch({ ...action, payload: result, status: 'resolved', }) + return result }) + + const pendingAction = { + ...action, + payload: promise, + status: 'pending', + } + // Propagate this action. Only attach listeners to the promise. + next(pendingAction) + + promise .catch(err => { store.dispatch({ ...action,