Q: Premature Promise Fulfillment in createAsyncThunk So I have this code here that requires the second call to be based on a param returned from the first call. So I chain it like so.
export const fetchUserInfo = createAsyncThunk(
  'fetchUserInfo',
  async (param1) =>
    axios
      .get(process.env.FIRST_CALL, {
        params: { code: param1 },
      })
      .then((firstCallResponse) => {
        axios
          .get(process.env.SECOND_CALL, {
            headers: {
              token: firstCallResponse.data.token,
            },
          })
          .then((secondCallResponse) => {
            return {
              status: LoginStatus.SUCCESS,
              payload: { firstCallResponse, secondCallResponse },
            }
          })
          .catch((error) => {
            console.log(error)
            return { status: LoginStatus.SECONDCALL_FAILURE, payload: {} }
          })
      })
      .catch((error) => {
        console.log(error)
        return { status: LoginStatus.FIRSTCALL_FAILURE, payload: {} }
      }),
)

Unfortunately, this call triggers the extraReducer fetchUserInfo.fullfilled and sends back a response before it can successfully complete the axios.get(SECOND_CALL)
How do you set up a promise chain so that it must wait for all the the axios.get's to succeed or fail?

A: Your first API call's promise is not serialized with the second API call's promise. Because you didn't return the promise created by axios.get(SECOND_CALL).
An working example:
import { configureStore, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';

const LoginStatus = {
  SUCCESS: 'SUCCESS',
  SECONDCALL_FAILURE: 'SECONDCALL_FAILURE',
  FIRSTCALL_FAILURE: 'FIRSTCALL_FAILURE',
};

export const fetchUserInfo = createAsyncThunk('fetchUserInfo', async () =>
  axios
    .get('https://jsonplaceholder.typicode.com/users/1')
    .then((firstCallResponse) => {
      return axios
        .get('https://jsonplaceholder.typicode.com/users/2')
        .then((secondCallResponse) => {
          return {
            status: LoginStatus.SUCCESS,
            payload: { firstCallResponse: firstCallResponse.data, secondCallResponse: secondCallResponse.data },
          };
        })
        .catch((error) => {
          return { status: LoginStatus.SECONDCALL_FAILURE, payload: {} };
        });
    })
    .catch((error) => {
      console.log(error);
      return { status: LoginStatus.FIRSTCALL_FAILURE, payload: {} };
    }),
);

const userInfoSlice = createSlice({
  name: 'user',
  initialState: {},
  reducers: {},
  extraReducers(builder) {
    builder.addCase(fetchUserInfo.fulfilled, (state, action) => {
      console.log(action);
      return state;
    });
  },
});

const store = configureStore({ reducer: userInfoSlice.reducer });

store.dispatch(fetchUserInfo());

Output:
{
  type: 'fetchUserInfo/fulfilled',
  payload: {
    status: 'SUCCESS',
    payload: { firstCallResponse: [Object], secondCallResponse: [Object] }
  },
  meta: {
    arg: undefined,
    requestId: 'l0lJmWjt2BMsVjbJUvVs1',
    requestStatus: 'fulfilled'
  }
}

