【发布时间】:2020-08-21 06:02:04
【问题描述】:
我有一个压缩文件的函数,但 atm 它返回一个承诺。我试图实现这一点:jszip stackoverflow 但它仍然返回承诺,未解决。
我对 Promise 不太熟悉,对 jsZIP 也完全不熟悉 - 我如何让这个函数返回压缩文件?
const getZip = (url) => {
setLoadingStatus('zipping...')
let zip = new JSZip();
console.log("TYPOF URL", url, typeof url)
zip.file("Report", url)
var promise = null;
if (JSZip.support.uint8array) {
promise = zip.generateAsync({type : "uint8array"}).then(content => {
saveAs(content, "Report.zip");
});
} else {
promise = zip.generateAsync({type : "string"}).then(content => {
saveAs(content, "Report.zip");
});
}
console.log("TYPEOF PROMISE", promise, typeof promise) //typeof is always promise
return promise
}
使用异步等待:
async function getZip(url){
setLoadingStatus('zipping...')
let zip = new JSZip();
console.log("TYPOF URL", url, typeof url)
zip.file("Report", url)
var content = null;
if (JSZip.support.uint8array) {
content = await zip.generateAsync({type : "uint8array"}).then(content => {
saveAs(content, "Report.zip");
})
} else {
content = await zip.generateAsync({type : "string"}).then(content => {
saveAs(content, "Report.zip");
})
}
return content
}
调用getZip()的函数是:
const createURL = useCallback((node, reportHeight, reportWidth, imgHeight) => {
domtoimage.toJpeg(node, {width: reportInViewerRef.current.offsetWidth, height: reportInViewerRef.current.scrollHeight})
.then(function (dataUrl) {
const pdf = new jsPDF('p', 'px', [reportWidth, imgHeight]);
setLoadingStatus('pdf created')
pdf.addImage(dataUrl, 'JPEG', 0, -12, reportWidth, reportHeight );
setLoadingStatus('image added')
let fileName = getUniqueFilename()
let base64pdf = getZip(btoa(fileName, pdf.output()));
console.log("ZIP FILE =================", base64pdf)
let storageRef = firebase.storage().ref();
setLoadingStatus('uploading...')
let fileLocation = '/pdfs/' + fileName + '.zip'
let reportPdfRef = storageRef.child(fileLocation);
reportPdfRef.putString(base64pdf, 'base64').then(function() {
console.log('Uploaded a data_url string!', reportPdfRef,
reportPdfRef.getDownloadURL().then(function(url) {
setLoadingStatus('linking...')
setTemplateParams({
to: sessionData.customerEmail,
customers: name,
adviser: adviserFullName,
adviserEmail: adviserEmail,
adviserAvatar: adviserAvatar,
content: url
})
firebase
.firestore()
.collection('sessions')
.doc(sessionData.id)
.update({
'pdfDownloadURL': url
}).then(function() {
setLoadingStatus('sending email')
setSendingEmail(false);
});
}).catch(function(error) {
switch (error.code) {
case 'storage/object-not-found':
console.log("FILE DOES NOT EXIST")
break;
case 'storage/unauthorized':
console.log("USER DOES NOT HAVE PERMISSION TO ACCESS THIS FILE")
break;
case 'storage/canceled':
console.log("USER CANCELLED THE UPLOAD")
break;
case 'storage/unknown':
console.log("SERVER ERROR")
break;
}
})
)
});
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
}, [])
【问题讨论】:
-
最简单的就是使用 async/await。因此,使函数异步,然后执行
let content= await zip.generateAsync(...); saveAs(content, "Report.zip");之类的操作,然后如果在其他地方需要,您可以返回内容。 -
你能举个例子吗?抱歉,我对异步等待不太熟悉
-
你为什么用
reactjs标记这个问题?我看不到任何与反应有关的东西。如果您打算在反应组件中使用它并且您不知道如何也请添加相关代码。否则只需删除标签。正如您似乎调用setLoadingStatus一样,我猜这个函数是使用useState在组件内部定义的? -
这就是一个例子,哈哈,这正是你所需要的。所以在函数定义中你输入
async,就像这样:const getZip = async (url)...,然后你在我的第一条评论中使用该代码。.then中的“内容”变成了等待调用的返回值,这就是为什么现在不需要promise变量,只需将其重命名为content。 -
你在哪里打电话给
getZip?请同时显示周围的组件。
标签: reactjs es6-promise jszip