angular - 关于异步函数的问题以及我应该如何正确同步运行它
问题描述
我有以下算法:
// Main Function
// Get some local data
// Convert to some format I need to edit
// Loop through user's local images
// Edit the converted data to add the image's names to it
// Convert IMAGE to base64 and add result into zip file
that.uriToBase64(imageFilePath).then((result) => {
console.log("image as base64: ", result);
zip.file(arrayItem2.name, result, {base64: true});
});
// Convert data again to save it
// Add data to zip file
// Generate zip file and save it in user's local storage
//uriToBase64() function
我的问题
“将数据添加到 zip 文件”步骤发生在将图像添加到 zip 文件之前。虽然“将 IMAGE 转换为 base64”步骤有一个 .then,但里面的所有内容只有在所有内容完成后才会发生。在这种情况下,我的 zip 文件在没有图像的情况下被保存。我试图使这一步同步工作,以无数种方式使用 async/await 语法,但我无法让它按我预期的方式工作,即在每次迭代中将图像数据添加到 zip 文件中。
由于 uriToBase64() 函数的结果是一个 Promise,使用 .then 来获取结果数据应该“暂停”循环,直到数据被 zip.file() 命令添加,然后迭代下一个图像,对吗?如果不是,考虑到算法的当前结构,等待它的正确方法是什么?
尝试
尝试 1
我尝试了一些令人讨厌的事情来完成这项工作,但再次失败。我的新算法:
// Main Function
// Get some local data
// Convert to some format I need and add to a global variable
// Loop through user's local images
// Add +1 to new global variable 'imageCounter'
// Edit the converted data (now in global variable) to add the image's names to it
// Convert IMAGE to base64 and add result into zip file
that.uriToBase64(imageFilePath).then((result) => {
console.log("image as base64: ", result);
zip.file(arrayItem2.name, result, {base64: true});
that.prepareForWrite();
// Check if this is the last iteration and run function again.
if (thisIsLastIteration == true) { that.prepareForWrite(); }
});
//prepareForWrite() function
// imageCounter - 1
// if imageCounter < 1
// Convert data again to save it
// Add data to zip file
// Generate zip file and save in user's local storage
//uriToBase64() function
这样我可以正确接收所有数据,但是“生成 zip 文件并将其保存在用户的本地存储中”只添加了第一个图像,并且它最终损坏了。
尝试 2
正如我之前所说,我已经用 async/await 做了很多尝试。我还将整个功能划分为较小的功能,并尝试在我需要先执行的部分上进行异步/等待。我最后一次使用 async/await 的尝试与此类似:
// async Main Function
// Get some local data
// Convert to some format I need to edit
// Loop through user's local images
// Edit the converted data to add the image's names to it
// Convert IMAGE to base64 and add result into zip file
let result = await that.uriToBase64(imageFilePath);
console.log(result);
zip.file(arrayItem2.name, result, {base64: true});
// Convert data again to save it
// Add data to zip file
// Generate zip file and save it in user's local storage
//uriToBase64() function
尝试 3
好的,经过一些测试,我能够以uriToBase64()
几种不同的方式从函数中同步获取数据。无论我如何接收 base64 字符串,生成 ZIP 文件后的结果始终相同:文件中只有一个压缩和损坏的图像,其他图像和主文件被忽略。
这让我想知道:也许问题是在生成 ZIP 文件之前如何压缩文件。所以我去找了这个问题的一些答案。我发现 JSZIP 库中包含一个函数,据我了解,它允许检查已添加到 ZIP 文件中的内容。考虑到这一点,我寻找了一些相关的问题,这导致了我这个问题。在这种情况下,每次添加文件时,相同的函数都会返回文件完成响应。
这就是我试图做的:
mainFunction() {
let string64 = 'veryLongBase64String';
let b64s = [];
let arrayOfPromises = [];
b64s.push(string64);
b64s.push(string64);
console.log(b64s);
b64s.forEach((b64, index) => {
let fileName = index + ".jpg";
arrayOfPromises.push(this.addFileToZip(fileName, b64));
});
Promise.all(arrayOfPromises)
.then(this.zip.generateAsync({type:"blob"})
.then((content) => {
let filePath = this.file.externalRootDirectory + '/app_downloads/';
this.file.writeFile(filePath, "testZip.zip", content).then(() => {
alert("File saved!");
})
.catch((err) => {
alert("Error while creating file: " + JSON.stringify(err));
});
})
);
}
addFileToZip(name: string, b64: string): Promise<string> {
this.zip.file(name, b64, {base64: true});
return this.zip.file(name).async("uint8array");
}
解决方案
@rapropos在这里回答的问题
基本上在获取base64字符串后,在生成ZIP文件时,默认情况下生成的文件类型是blob
错误的原因。更改类型以arraybuffer
解决问题。
推荐阅读
- r - 如何在多级层次结构上使用具有不同数量时间序列的“hts”?
- php - PHP bindParam 函数不起作用
- linux - 带有 netlink 套接字的 POLLERR
- python - DLL 包装教程中的 Cython setup.py 编译错误:无法解析的外部符号
- laravel-5.4 - 我无法在 laravel 中的多个路由组上访问相同的路由
- asp.net - 我在默认网站下将 ASP.NET CORE 2.0 WebApi 部署到 IIS 时收到 Not found 错误
- angular - 如何从 ParamMap 中获取路由参数并将其分配给属性
- wordpress - 检查产品是否可在 Woo commerce 中下载
- sql - 获取 TSQL 层次结构路径
- javascript - 将文本从文本框传递到 jsp 中的 href 调用的按钮