Promise与异步操作问题:二次请求提前执行的技术求助
问题根源分析
你遇到的核心问题是第一个异步请求updatePU没有被正确等待。看一下你的代码:
const promise = new Promise((resolve, reject) => { resolve(this.updatePU(name, 'text', selectedOption.code)); })
这里你手动创建了一个Promise,但updatePU是异步函数,它内部调用了fetch却没有返回这个异步操作的Promise链。所以当你调用resolve(this.updatePU(...))时,resolve接收的其实是undefined(因为updatePU没有返回值),导致这个手动创建的Promise立刻就变成了resolved状态,直接执行后面的then回调——完全没等updatePU的请求完成。
解决方案
我们只需要两步就能修复这个问题:
1. 让updatePU返回它的Promise链
修改updatePU函数,在fetch前面加上return,这样整个函数会返回异步操作的Promise,外部就能等待它完成:
updatePU = (name, type, value) => { const PUOrderNo = this.props.puOrderNo; const updatedValue = type === 'text' ? (`'${name}': '${value}'`) : (`'${name}': ${value}`); // 关键:返回fetch的Promise链 return fetch('/ModifyPUOrder', { crossDomain: true, method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ updatedValue: updatedValue, puOrderNo: PUOrderNo }), }) .then(response => { if(response.ok){ return response.json(); } else { console.log(response); throw new Error('Request failed!'); } }, networkError => { console.log(networkError.message); throw networkError; // 抛出错误,让外部catch能捕获到 }) .then(data => { if ("error" in data) { alert(data.error.message); this.refresh(); } this.props.updatePUOrderForm(data); }); }
2. 直接使用updatePU返回的Promise,去掉手动创建的Promise
现在updatePU已经返回Promise了,我们可以直接链式调用then,不需要再手动包裹Promise:
this.updatePU(name, 'text', selectedOption.code) .then(() => { console.log('Calling checkExpress function'); const puOrderNo = this.props.puOrderNo; // 这里也建议return这个fetch的Promise,让错误能被外部catch捕获 return fetch('/CheckExpress', { crossDomain: true, method: 'POST', headers: { 'Accept': 'text/xml', 'Content-Type': 'application/json', }, body: JSON.stringify({"puOrderNo": puOrderNo }) }) .then(response => response.text()) .then(str => convert.xml2json(str)) // 可以直接返回,不用存到变量里 .then(express => { const data = JSON.parse(express); const checkExpress = data['elements'][0].elements[0].elements[0].elements[0].elements[0].text; console.log('checkExpress:', checkExpress); // 简化写法 this.props.updatePackageTypeField(checkExpress === 'true'); }) }) .catch(err => console.log('Request error:', err)); // 统一捕获所有错误
额外优化点
- 去掉了不必要的变量
express,直接在then中传递转换后的结果,代码更简洁。 - 统一了错误捕获,把两个请求的错误都放到最外层的
catch里处理,避免遗漏。 - 在
updatePU的networkError回调里添加了throw networkError,确保网络错误能被外层捕获。
这样修改后,第一个请求updatePU完成后才会执行第二个CheckExpress请求,顺序就正确了。
内容的提问来源于stack exchange,提问作者Morgana
相关产品推荐
相关产品推荐

