Axios POST 请求花费的时间太长并且在 WebApi 上被重复
Axios POST requests taking too long and being duplicated at WebApi
今天我收到错误报告,指出我们应用程序的某些 POST 请求被重复。
这些请求导致在远程数据库上创建 objects,例如任务、会议等,因此它们的重复意味着创建的任务具有相同的名称、相同的截止日期、相同的用户、等等
我已经尝试复制它,但它似乎是一种随机行为,报告的唯一并发症状是请求比正常情况下需要更多时间才能完成。
我目前正在使用堆栈 React + Redux + Axios + Asp.Net WebApi,为了 理解 和 解决问题。
非常感谢关于这些主题的任何提示。
根本原因识别
React + Redux:
调度请求的动作创建者仅在 onClick 事件中被调用一次。显然没有状态更改或页面刷新可能导致多次调用此功能。
handleClick(event) {
var postData = {
title: this.state.text,
dueDate: this.state.date,
assignedUser: this.state.user.id
};
this.props.contentPost(postData);
}
Axios:
我的一个怀疑是,出于某种未知原因,用户的请求失败,或者需要很长时间才能完成,然后 axios 应该会再次发送请求。我检查了它的文档和问题数据库,没有发现自动重试或请求重复之类的东西。
export const contentPost = (props) => {
return function (dispatch) {
dispatch({ type: CONTENT_POST_ERROR, payload: null })
dispatch({ type: CONTENT_POST_LOADING, payload: true });
dispatch({ type: CONTENT_POST_SUCCESS, payload: null })
const request = axios({
method: 'post',
url: `/api/content`,
headers: auth.getHttpHeader(),
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
data: props
}).then((res) => {
dispatch({ type: CONTENT_POST_LOADING, payload: false });
dispatch({ type: CONTENT_POST_SUCCESS, payload: true, data: res })
}).catch(err => {
dispatch({ type: CONTENT_POST_ERROR, payload: err.code })
dispatch({ type: CONTENT_POST_LOADING, payload: false });
dispatch({ type: CONTENT_POST_SUCCESS, payload: false, data: null })
});
}
};
WebApi
Controller 的方法没有任何类型的限制或 "uniqueness token" 来识别和防止重复的请求。由于这是随机行为,我敢打赌路由或我的服务器端应用程序的任何部分对此不承担任何责任。
目前的解决方案...
Axios:
- 限制我的动作创建者的 axios 请求,以防止在给定的时间间隔内经常调用它。
- 在请求正文中发送一个client-generated"uniqueness token"
WebApi
- 执行请求 filtering/throttling,以防止重复请求,基于给定时间间隔的正文内容。
- 接收并处理 "uniqueness token" 以防止 post 口是心非。
即使有了上述描述,这些解决方案看起来还是矫枉过正,而根本原因似乎也有点太主观了。
我发现用户的延迟加载状态反馈导致了此行为。
有些人仍然会双击网站上的东西。没有通过代码阻止这种情况是天真的。
在这种情况下,有很多方法可以实现更好的用户体验。我选择在用户发送我们的 POST 请求时完全更改按钮,我们还在后端实施节流。
{this.props.content_post_loading &&
<a className="btn btn-primary disabled">Creating...</a>
||
<a className="btn btn-primary" onClick={this.handleCreateClick}>Create</a>
}
今天我收到错误报告,指出我们应用程序的某些 POST 请求被重复。
这些请求导致在远程数据库上创建 objects,例如任务、会议等,因此它们的重复意味着创建的任务具有相同的名称、相同的截止日期、相同的用户、等等
我已经尝试复制它,但它似乎是一种随机行为,报告的唯一并发症状是请求比正常情况下需要更多时间才能完成。
我目前正在使用堆栈 React + Redux + Axios + Asp.Net WebApi,为了 理解 和 解决问题。
非常感谢关于这些主题的任何提示。
根本原因识别
React + Redux:
调度请求的动作创建者仅在 onClick 事件中被调用一次。显然没有状态更改或页面刷新可能导致多次调用此功能。
handleClick(event) {
var postData = {
title: this.state.text,
dueDate: this.state.date,
assignedUser: this.state.user.id
};
this.props.contentPost(postData);
}
Axios:
我的一个怀疑是,出于某种未知原因,用户的请求失败,或者需要很长时间才能完成,然后 axios 应该会再次发送请求。我检查了它的文档和问题数据库,没有发现自动重试或请求重复之类的东西。
export const contentPost = (props) => {
return function (dispatch) {
dispatch({ type: CONTENT_POST_ERROR, payload: null })
dispatch({ type: CONTENT_POST_LOADING, payload: true });
dispatch({ type: CONTENT_POST_SUCCESS, payload: null })
const request = axios({
method: 'post',
url: `/api/content`,
headers: auth.getHttpHeader(),
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
data: props
}).then((res) => {
dispatch({ type: CONTENT_POST_LOADING, payload: false });
dispatch({ type: CONTENT_POST_SUCCESS, payload: true, data: res })
}).catch(err => {
dispatch({ type: CONTENT_POST_ERROR, payload: err.code })
dispatch({ type: CONTENT_POST_LOADING, payload: false });
dispatch({ type: CONTENT_POST_SUCCESS, payload: false, data: null })
});
}
};
WebApi
Controller 的方法没有任何类型的限制或 "uniqueness token" 来识别和防止重复的请求。由于这是随机行为,我敢打赌路由或我的服务器端应用程序的任何部分对此不承担任何责任。
目前的解决方案...
Axios:
- 限制我的动作创建者的 axios 请求,以防止在给定的时间间隔内经常调用它。
- 在请求正文中发送一个client-generated"uniqueness token"
WebApi
- 执行请求 filtering/throttling,以防止重复请求,基于给定时间间隔的正文内容。
- 接收并处理 "uniqueness token" 以防止 post 口是心非。
即使有了上述描述,这些解决方案看起来还是矫枉过正,而根本原因似乎也有点太主观了。
我发现用户的延迟加载状态反馈导致了此行为。
有些人仍然会双击网站上的东西。没有通过代码阻止这种情况是天真的。
在这种情况下,有很多方法可以实现更好的用户体验。我选择在用户发送我们的 POST 请求时完全更改按钮,我们还在后端实施节流。
{this.props.content_post_loading &&
<a className="btn btn-primary disabled">Creating...</a>
||
<a className="btn btn-primary" onClick={this.handleCreateClick}>Create</a>
}