CDN模式ReactJS集成AXIOS请求异常及await报错问题求解
问题根因
你遇到的异常来自代码写法错误和React生命周期使用错误,具体如下:
- 第一版代码无日志的可能原因:
- 先检查控制台是否有
App is not defined报错、Network面板中App.js的请求是否返回200:你用type="text/babel"引入外部App.js时,如果路径写错、服务器返回404,App组件根本不会注册,后续渲染和请求逻辑完全不会执行。 - 你把axios请求直接写在函数组件的渲染函数顶层,属于在React渲染阶段直接触发副作用,执行时机不可控,组件重渲染时还会重复触发请求。如果请求触发跨域预检失败、网络层异常,未被正确捕获时不会进入你写的then/catch回调链,就会出现无日志的情况。
- 先检查控制台是否有
- await语法报错的原因:
await关键字只能在被async标记的异步函数内部使用,你直接在普通的Product函数顶层写await,babel转译阶段就会抛出语法错误,整段代码都不会执行。另外你第二版代码还有两处错误:axios返回结果本身就是响应Promise,不需要再传给fetch调用;response.jso()是拼写错误,正确方法是response.json()。
修复方案
React中数据请求属于副作用逻辑,必须在组件挂载完成后触发,仅执行一次。以下是可直接运行的修复代码:
方案1:保留Promise链式调用(适配第一版代码)
替换App.js内容为以下代码,同时删掉index.html里内联的ReactDOM.render代码,直接在App.js末尾执行渲染即可:
class App extends React.Component { componentDidMount() { // 组件挂载完成后执行,仅触发一次 axios.post('http://<domainName>.com/api/product_ec7cac9007758d89656160f668_1381') .then(function (response) { console.log("result response"); console.log(response); // 后续可将数据存入setState用于页面渲染 }) .catch(function (error) { console.log("result error"); console.log(error); // 跨域、网络错误、接口报错都会在这里捕获 }) .finally(function () { console.log("last"); }); } render() { return( <div> DISPLAY PRODUCT DETAIL </div> ) } } ReactDOM.render(<App />, document.getElementById("root"));
方案2:async/await写法(适配第二、第三版代码)
使用async/await必须先定义异步函数,再在生命周期钩子中调用:
class App extends React.Component { // 定义异步请求方法 async loadProductData() { try { // axios请求写法 const response = await axios.post("http://<domainName>.com/api/product_ec7cac9007758d89656160f668_1381", {}, { headers: { "Content-Type": "application/json", Accept: "application/json" } }); console.log("接口响应", response); // fetch请求写法(和axios二选一即可,不要混用) // const fetchOptions = { // method: "POST", // headers: { // "Content-Type": "application/json", // Accept: "application/json" // } // }; // const fetchRes = await fetch('http://<domainName>.com/api/product_ec7cac9007758d89656160f668_1381', fetchOptions); // const data = await fetchRes.json(); // console.log("fetch结果", data); } catch (err) { console.log("请求异常", err); } finally { console.log("请求流程结束"); } } componentDidMount() { this.loadProductData(); } render() { return <div>DISPLAY PRODUCT DETAIL</div> } } ReactDOM.render(<App />, document.getElementById("root"));
注意事项
- 如果控制台出现CORS跨域相关报错,说明你当前运行页面的源(localhost:81)和接口源不一致,后端接口没有配置跨域允许规则,需要后端给接口添加
Access-Control-Allow-Origin响应头解决,前端代码无法绕过浏览器跨域限制。 - 用babel-standalone加载外部js文件时,要确保服务器给js文件返回正确的
application/javascriptMIME类型,否则会出现转译失败、代码不执行的问题。 - 不要把副作用逻辑(接口请求、DOM操作、定时器)直接写在render函数或者函数组件顶层,避免重复执行、时机异常的问题。
内容的提问来源于stack exchange,提问作者ferdinand
相关产品推荐
相关产品推荐

