为何Async/Await调用getPageFiles后返回Promise而非对象列表?
问题:调用getPageFiles返回Promise数组而非文件对象列表
尝试从getPageFiles函数获取文件对象,要求两次axios请求完成且第二个请求成功后返回该对象,但调用后得到的files是Promise数组而非预期的对象列表。
相关代码:
async function getPageFiles() { return connectionInfo.files.map( (file) => { return axios .post( API_ROUTE, { file_name: file.file_name, }, { headers: { "Content-Type": "application/json", authorization, }, params: { presignedUrl: true }, } ) .then((response: any) => { const res = JSON.parse(response); // PUT request: upload file to S3 return axios .put(res.uploadURL, file.binary) .then((s3Response: TResponseError | any) => { return { file_type: "csv", s3_path: `s3://${process.env.TEST}/${file.file_name}`, table_name: file.table_name.toUpperCase(), } } ) .catch((error) => { // eslint-disable-next-line no-console console.error(`Error putting file to s3 upload URL: ${error}`); }); }); } ); }; let files = await getPageFiles();
原因分析
getPageFiles内部使用map遍历文件列表时,每个迭代项返回的都是axios请求的Promise实例,所以map最终返回的是一个Promise数组,而非resolved后的对象数组。即使函数标记为async,直接返回这个数组的话,await只会等待数组本身(不会等待数组内所有Promise完成),因此files最终还是Promise数组。
解决方案
用Promise.all()包裹map的结果,让async函数等待所有Promise都完成后,返回resolved后的对象数组:
修改后的代码:
async function getPageFiles() { // 用Promise.all等待所有请求完成 return Promise.all( connectionInfo.files.map( (file) => { return axios .post( API_ROUTE, { file_name: file.file_name, }, { headers: { "Content-Type": "application/json", authorization, }, params: { presignedUrl: true }, } ) .then((response: any) => { const res = JSON.parse(response); // PUT request: upload file to S3 return axios .put(res.uploadURL, file.binary) .then((s3Response: TResponseError | any) => { return { file_type: "csv", s3_path: `s3://${process.env.TEST}/${file.file_name}`, table_name: file.table_name.toUpperCase(), } } ) .catch((error) => { // eslint-disable-next-line no-console console.error(`Error putting file to s3 upload URL: ${error}`); // 返回默认值避免Promise.all整体失败 return null; }); }); } ) ); }; let files = await getPageFiles(); // 此时files是resolved后的对象列表(失败项会是你定义的默认值,比如null)
补充说明
Promise.all()会等待数组中所有Promise都resolved,然后返回包含所有结果的数组;如果有任意一个Promise被reject,Promise.all()会立即reject。- 如果想让个别请求失败不影响整体结果,可在catch中返回默认值(如
null),这样Promise.all()会继续等待其他请求完成,最终结果数组对应位置会是你返回的默认值。
内容的提问来源于stack exchange,提问作者ksusha-beep
相关产品推荐
相关产品推荐

