RTK Query: `await` when using `onQueryStarted` is not working

1.7k Views Asked by At

I'm facing a strange problem.

I have an object inside my global state that needs to be populated with 3 different API endpoint calls.

So I choose to set one specific query with onQueryStarted method.
And make the 3 API calls together inside this method.

This are the endpoints from api.ts service:

{
    scenario: builder.query({ query: ({theid}) => `scenarios/${scenarioId}`}),
    milestones: builder.query({ query: ({theid}) => `scenarios/${scenarioId}/ml`}),
    groups: builder.query({ query: ({theid}) => `scenarios/${scenarioId}/pg`}),

    setCurrentScenario: builder.query({
        query: id => `scenarios/${id}`, 
        async onQueryStarted (id, { dispatch, queryFulfilled, getState }) {
            try {
                let ml = await api.endpoints.milestones.initiate({theid: id})(dispatch, getState, "api")
                let pg = await api.endpoints.groups.initiate({theid: id})(dispatch, getState, "api")
                    
                let currentScen = await queryFulfilled
                dispatch( scenarioActions.addCurrentScenario( currentScen.data ))
                dispatch( scenarioActions.addCurrentScenarioMilestones( ml.data ))
                dispatch( scenarioActions.addCurrentScenarioPlayerGroups( pg.data ))
                    
            } catch (error) {
                console.log('ERRORE IN SETCURRENTSCENARIO: ', error)
            }
}

This works fine, BUT when I'm testing I need to add some "sleep" function, despite the fact that I dispatch the setCurrentScenario endpoint with an await:

describe('A single Scenario should be fetched if user is manager', () => {
    it('should populate `current` scenario after asking with its `id`', async () => {

            // this populates `state.scenarios.current` 
            await store.dispatch( api.endpoints.setCurrentScenario.initiate( 1 ) )
            
            const sleep = (time:number) => new Promise((reslv) => setTimeout(reslv, time));
            await sleep(1000)

            const currentScenario = store.getState().scenarios.current
            console.log({currentScenario})

            expect(store.getState().scenarios.current?.name).not.toBeNull()
    })
})

I don't get it, why I need to sleep if I use await on that store.dispatch() ?

thanks for any help you can give me.

1

There are 1 best solutions below

2
phry On

Because await means "do this and we continue executing our code later".

Other code - in this case, your test - can run in-between. So your test has to finished until all the things are done and all the "later" code has executed, too.