Axios封装异步函数返回Promise,调用后控制台输出undefined问题排查
问题
我编写了一个集中处理所有Axios请求的异步函数callApi,代码如下:
export async function callApi(apiOptions) { let headers = { 'X-Client-ID': '********************', //using * for security purposes 'X-Client-Secret': '******************', //same }; if (apiOptions.headers !== undefined) { apiOptions.headers.forEach(header => { headers[header.name] = header.value; }); } let options = {}; options = { url: apiOptions.endpoint, method: apiOptions.method, baseURL: process.env.REACT_APP_API_BASE_URL, headers: headers, data: apiOptions.data, }; await axios(options) .then(response => { console.log(response); //200 status code return response; }) .catch(error => { return error; }); }
该函数接收options对象并发送Axios请求,本应将响应返回给调用方。但当我在useEffect中调用该函数并打印响应时,输出为undefined:
useEffect(() => { let options = { endpoint: '/password-policy', method: 'GET', }; callApi(options) .then(response => { console.log('RES', response); // consoles 'undefined' }) .catch(err => { console.log('err', err); }); }, [width]);
请帮忙指出问题所在,非常感谢。
问题原因与修复方案
问题核心
callApi是async函数,但你没有返回axios请求的最终结果。虽然你在then回调里return了response,但这个return只作用于then的回调函数,外层的callApi函数没有把整个axios调用的结果return出去。async函数如果没有显式return值,默认会返回undefined,这就是调用方拿到undefined的原因。
修复方式一:return axios请求的结果
直接在await axios(...)前加上return,让async函数把请求结果返回:
export async function callApi(apiOptions) { let headers = { 'X-Client-ID': '********************', 'X-Client-Secret': '******************', }; if (apiOptions.headers !== undefined) { apiOptions.headers.forEach(header => { headers[header.name] = header.value; }); } const options = { url: apiOptions.endpoint, method: apiOptions.method, baseURL: process.env.REACT_APP_API_BASE_URL, headers: headers, data: apiOptions.data, }; // 加上return,把axios请求的结果返回给调用方 return await axios(options) .then(response => { console.log(response); return response; }) .catch(error => { // 这里注意:如果return error,调用方会进入then而不是catch // 建议直接抛出错误,让调用方的catch捕获 throw error; }); }
修复方式二:用try/catch代替then/catch(更符合async/await写法)
async/await的设计就是为了替代Promise的then/catch链式调用,这样代码更简洁易读:
export async function callApi(apiOptions) { let headers = { 'X-Client-ID': '********************', 'X-Client-Secret': '******************', }; if (apiOptions.headers !== undefined) { apiOptions.headers.forEach(header => { headers[header.name] = header.value; }); } const options = { url: apiOptions.endpoint, method: apiOptions.method, baseURL: process.env.REACT_APP_API_BASE_URL, headers: headers, data: apiOptions.data, }; try { const response = await axios(options); console.log(response); return response; } catch (error) { console.error(error); // 抛出错误,让调用方的catch处理 throw error; } }
额外注意点
原代码中catch里直接return error会导致调用方的then被触发而不是catch,因为async函数return的任何值都会被包装成resolved的Promise。所以正确的做法是在catch里抛出错误,这样调用方的catch才能捕获到异常。
内容的提问来源于stack exchange,提问作者Rishav Gooptu
相关产品推荐
相关产品推荐

