问题描述
最近,当我尝试使用两个不同版本的API时遇到了这个问题。逻辑是如果API的v2
给我一个404错误,那么我将尝试v1
,如果没有错误,我将使用v2
这是我的尝试:我为每个版本创建了两个单独的异步thunk动作,然后在分配两个动作的地方创建了一个异步thunk。
export const getV2LoggingOptions = createAsyncThunk(
"settings/getV2LoggingOptions",async () => {
return sdkClient.getV2LoggingOptions().promise();
}
);
export const getV1LoggingOptions = createAsyncThunk(
"settings/getV1LoggingOptions",async () => {
return sdkClient.getV1LoggingOptions().promise();
}
);
export const getLoggingOptions = createAsyncThunk(
"settings/getLoggingOptions",async (arg,thunkApi) => {
let response = await thunkApi.dispatch(getV2LoggingOptions());
if (response.error) {
if (
response.error.statusCode === "404"
) {
response = await thunkApi.dispatch(getV1LoggingOptions());
}
throw response.error;
}
return response.payload;
}
);
我认为这种方法可行。但不确定这是否是最好的方法。现在,这种方法存在两个问题:
- 我不知道如何像
let response = await thunkApi.dispatch(getV2LoggingOptions());
那样正确键入此响应。 - 此外,
error
内部的response
属性(如果v2
调用失败)不包含statusCode
属性。所以我看不懂对于它为什么不包含statusCode
的问题,这确实令我感到困惑
另一种方法是只创建一个异步thunk并直接在内部调用两个版本
export const getLoggingOptions = createAsyncThunk(
"settings/getLoggingOptions",async () => {
let response;
try {
response = await sdkClient.getV2LoggingOptions().promise();
} catch (error) {
if (
error.statusCode === "404"
) {
response = await sdkClient.getV1LoggingOptions().promise();
}
throw error;
}
return response;
}
);
它似乎也在工作。但是问题是,我仍然不确定如何在此处键入response
。
API确实提供了其响应的输入方式。 GetV1LoggingOptionsResponse
和GetV2LoggingOptionsResponse
。但是我不确定应该将响应键入为
let response: GetV1LoggingOptionsResponse | GetV2LoggingOptionsResponse
从那时起,我只能从响应中读取这两种类型的重叠部分。
在第二种方法中,statusCode
也被error
子句中的catch
所丢失。
解决方法
由于两个api都有不同的返回值,因此它们可能应该是不同的asyncThunks,因此您应该分别处理它们的操作。
另外,您应该在相应的asyncThunks内部进行错误处理(包括抛出),因为这将导致您可以在化简器中处理rejected
动作。
一旦有了这两个asyncThunk,就没有理由再使用第三个asyncThunk来介绍它自己实际上不需要的生命周期操作,因为这实际上只是另外两个的编排。
写一个普通的thunk:
const getLogginOptions = () => async (dispatch) => {
let result = await dispatch(getV2LoggingOptions());
if (getV2LoggingOptions.rejected.match(result)) {
result = await dispatch(getV1LoggingOptions());
}
return result;
}