表单提交后完成全部POST请求再跳转页面的问题解决
解决表单提交时异步请求未完成就跳转的问题
我通过表单的onSubmit处理提交逻辑,流程是:先POST规则集获取ID,再逐个POST所有规则,全部完成后跳转到rulesets_modify页面。目前跳转能成功,但目标页面只能拿到规则集数据,规则数据要刷新后才显示,明显是跳转发生在所有规则POST请求完成之前。
相关代码
页面组件 rulesets_new
export default function NewRuleset() { // 表格列定义 // useState 声明 // 添加新规则的函数 // 获取API数据的useEffect const navigate = useNavigate(); return ( <> <Header text='Regelset aanmaken' /> <Form onSubmit={(event) => handleSubmit(event, RulesetName, EngineOid, ProcessOid, Rules, navigate)}> <RnRulesetsTopRow // 参数传递 /> <Row> <Col> <RnTable columns={columns} data={Rules} Rules={Rules} setRules={setRules} /> </Col> </Row> <Row> <Col> <Button type="submit" variant='success'>Save</Button> </Col> <Col> <Button className='float-right' onClick={(e) => addNewRule(e, setRules)}>+</Button> </Col> </Row> </Form> </> ) }
handleSubmit 函数
export function handleSubmit(e, RulesetName, EngineOid, ProcessOid, Rules, nav) { e.preventDefault(); var newRulesetJson = `{...}`; const RulesetPostOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: newRulesetJson }; postRuleset(RulesetPostOptions) .then(response => { Rules.forEach(Rule => { let seq = (Rule.SequenceNumber) ? Rule.SequenceNumber : ""; let name = (Rule.Name) ? Rule.Name : ""; let desc = (Rule.Description) ? Rule.Description : ""; let exp = (Rule.Expression) ? Rule.Expression : ""; let RuleJson = `{...}`; let RulesPostOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: RuleJson }; postRule(RulesPostOptions) }); nav('/rulesets_modify?rulesetOid='+response.Oid); }) };
postRuleset 函数
export const postRuleset = async (RulesetPostOptions) => { return fetch('api-url.com', RulesetPostOptions) .then(response => response.json()) .catch(error => console.log('error', error)) }
解决方案
问题出在handleSubmit里的Rules.forEach循环——每个postRule都是异步请求,但循环不会等待这些请求完成,直接执行了后面的nav跳转。要解决这个问题,需要收集所有规则提交的Promise,用Promise.all等待全部完成后再跳转。
修改后的handleSubmit函数如下:
export function handleSubmit(e, RulesetName, EngineOid, ProcessOid, Rules, nav) { e.preventDefault(); var newRulesetJson = `{...}`; const RulesetPostOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: newRulesetJson }; postRuleset(RulesetPostOptions) .then(response => { // 用map收集所有postRule的Promise,代替forEach const rulePromises = Rules.map(Rule => { let seq = (Rule.SequenceNumber) ? Rule.SequenceNumber : ""; let name = (Rule.Name) ? Rule.Name : ""; let desc = (Rule.Description) ? Rule.Description : ""; let exp = (Rule.Expression) ? Rule.Expression : ""; let RuleJson = `{...}`; let RulesPostOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: RuleJson }; return postRule(RulesPostOptions); // 返回Promise }); // 等待所有规则提交完成后再跳转 return Promise.all(rulePromises).then(() => response); }) .then(response => { nav('/rulesets_modify?rulesetOid='+response.Oid); }) .catch(error => { // 这里可以添加错误处理,比如提示用户提交失败 console.error('提交规则失败:', error); }); };
关键说明
Array.map代替forEach:map会返回一个包含所有Promise的数组,而forEach只是执行操作,不返回值。Promise.all:等待数组中所有Promise都resolve后才会继续执行后续的then回调,确保所有规则都提交完成后再跳转。- 增加错误捕获:如果任何一个规则提交失败,都会进入catch,避免静默失败。
内容的提问来源于stack exchange,提问作者R. Gore
相关产品推荐
相关产品推荐

