问题场景:前端通过后端接口下载文件,返回值是一个blob文件,需要通过fileReader.onload()内部才能做各种判断,并且将res.data返回出去,但是fileReader.onload()是一个异步方法,直接reutrn fileReader.onload()是返回undefined。所以问题就是怎么把fileReader.onload()内部的变量传递出去呢?
一开始是想用闭包,但结果发现是undefined,应该是fileReader.onload()本身就没有返回值。结果就被卡住了。
后来想到一个新办法。
很简单,核心就是在第一个.then的处理逻辑中,继续返回Promise,然后在下一个Promise的.then中进行return
代码如下:
/**
* 下载(post请求)
* @param {string} url 请求地址
* @param {object} params 地址参数
*/
export const downloadPost = async function (url, data = {}, params={}) {
return await axios.post(url,data, {
...params,
responseType: 'blob',
headers: {
'X-AUTH-TOKEN' : getToken(),
},
}).then(res => {
return new Promise((resolve,reject)=>{
let fileReader = new FileReader();
fileReader.onload = function () {
try {
let response = JSON.parse(this.result); // 说明是普通对象数据,后台转换失败
if(typeof response == 'object') {
if (response.code) {
Notification.warning({
title: '提示',
message: `${response.msg}`,
})
return reject(response)
}
}else{
throw('message');
}
} catch (error) {
const name = window.decodeURI(res.headers['content-disposition'].split('=')[1]);
if (window.navigator.msSaveBlob) {
const blobObject = new Blob([res.data]);
window.navigator.msSaveBlob(blobObject, name);
} else {
let link = document.createElement('a');
link.href = window.URL.createObjectURL(res.data);
link.download = name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
return resolve(res.data)
}
};
fileReader.readAsText(res.data)
})
}).then(res=>{
return res
}).catch(err=>{
return Promise.reject(err);
});
}