首页 > 解决方案 > 关于异步函数的问题以及我应该如何正确同步运行它

问题描述

我有以下算法:

// 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");
}

标签: angulartypescriptasynchronousionic-frameworkionic4

解决方案


@rapropos在这里回答的问题

基本上在获取base64字符串后,在生成ZIP文件时,默认情况下生成的文件类型是blob错误的原因。更改类型以arraybuffer解决问题。


推荐阅读