Error handling in getCampaigns.

This commit is contained in:
Gan Eng Chin 2023-02-24 18:32:33 +08:00
parent 92762ca9b0
commit a982b7be21
No known key found for this signature in database
GPG Key ID: 94D5D972860ADB01
4 changed files with 62 additions and 33 deletions

View File

@ -43,7 +43,7 @@ export const receiveRecommendedChannelsError = ( error: ApiFetchError ) => {
};
};
export const receiveCampaignsSuccess = ( action: {
export const receiveCampaignsSuccess = ( success: {
payload: Array< Campaign >;
error: boolean;
meta: {
@ -54,15 +54,22 @@ export const receiveCampaignsSuccess = ( action: {
} ) => {
return {
type: TYPES.RECEIVE_CAMPAIGNS_SUCCESS,
...action,
...success,
};
};
export const receiveCampaignsError = ( error: ApiFetchError ) => {
export const receiveCampaignsError = ( error: {
payload: ApiFetchError;
error: boolean;
meta: {
page: number;
perPage: number;
total?: number;
};
} ) => {
return {
type: TYPES.RECEIVE_CAMPAIGNS_ERROR,
payload: error,
error: true,
...error,
};
};

View File

@ -14,6 +14,15 @@ export const fetchWithHeaders = (
};
};
export const awaitResponseJson = (
response: Response
): AnyAction & { response: Response } => {
return {
type: 'AWAIT_RESPONSE_JSON',
response,
};
};
const controls = {
...dataControls,
FETCH_WITH_HEADERS( action: AnyAction ) {
@ -36,6 +45,9 @@ const controls = {
} );
} );
},
AWAIT_RESPONSE_JSON( action: AnyAction ) {
return action.response.json();
},
};
export default controls;

View File

@ -80,7 +80,14 @@ export const reducer: Reducer< State, Action > = (
return {
...state,
campaigns: {
error: action.payload,
perPage: action.meta.perPage,
pages: {
...state.campaigns.pages,
[ action.meta.page ]: {
error: action.payload,
},
},
total: action.meta.total,
},
};

View File

@ -14,27 +14,16 @@ import {
receiveCampaignsSuccess,
receiveCampaignsError,
} from './actions';
import { fetchWithHeaders } from './controls';
import { RegisteredChannel, RecommendedChannel, Campaign } from './types';
import { awaitResponseJson } from './controls';
import {
RegisteredChannel,
RecommendedChannel,
Campaign,
ApiFetchError,
} from './types';
import { API_NAMESPACE } from './constants';
import { isApiFetchError } from './guards';
const getIntHeaderValues = (
response: {
headers: Map< string, string >;
data: unknown;
},
keys: string[]
) => {
return keys.map( ( key ) => {
const value = response.headers.get( key );
if ( value === undefined ) {
throw new Error( `'${ key }' header is missing.` );
}
return parseInt( value, 10 );
} );
};
export function* getRegisteredChannels() {
try {
const data: RegisteredChannel[] = yield apiFetch( {
@ -69,18 +58,19 @@ export function* getRecommendedChannels() {
export function* getCampaigns( page: number, perPage: number ) {
try {
const resp: {
headers: Map< string, string >;
data: Array< Campaign >;
} = yield fetchWithHeaders( {
const response: Response = yield apiFetch( {
path: `${ API_NAMESPACE }/campaigns?page=${ page }&per_page=${ perPage }`,
parse: false,
} );
const [ total ] = getIntHeaderValues( resp, [ 'x-wp-total' ] );
const total = parseInt(
response.headers.get( 'x-wp-total' ) || '0',
10
);
const payload: Campaign[] = yield awaitResponseJson( response );
yield receiveCampaignsSuccess( {
payload: resp.data,
payload,
error: false,
meta: {
page,
@ -89,9 +79,22 @@ export function* getCampaigns( page: number, perPage: number ) {
},
} );
} catch ( error ) {
// TODO: error is an HTTPResponse that hasn't been parsed.
if ( isApiFetchError( error ) ) {
yield receiveCampaignsError( error );
if ( error instanceof Response ) {
const total =
parseInt( error.headers.get( 'x-wp-total' ) || '0', 10 ) ||
undefined;
const payload: ApiFetchError = yield awaitResponseJson( error );
yield receiveCampaignsError( {
payload,
error: true,
meta: {
page,
perPage,
total,
},
} );
}
throw error;