首页 > 解决方案 > Typescript:axios 获取、文件写入和文件读取的异步问题

问题描述

我正在编写一个 Firebase 云函数,它下载一个文件,将其写入 /tmp/,然后尝试使用 docxtemplater 包将其解析为 Docx 文件。一旦启动并运行,我打算对该文件进行更多处理,但这不是重点。

到目前为止我写的问题通常有效,而在其他时候我收到以下错误:

`Error: ENOENT: no such file or directory, open '/tmp/template_file'`

当出现此错误时,再次运行该函数通常只会彻底解决问题并开始返回成功。然后我可以向这个函数发送垃圾邮件,我最终会得到一堆不同的成功而没有失败。这让我怀疑两个问题:

  1. 我的代码没有正确处理 axios 获取、写入和读取的异步部分。

  2. Firebase 函数会发生奇怪的缓存行为。然后,完全有可能(1)在这里完全有错。换句话说,第一次运行代码时,文件读取发生在初始下载完成之前(不完全确定为什么会发生这种情况——也许我在滥用 await / promises?),而后续功能运行成功,因为文件已下载。再说一次,如果这是真的,那将违背我的假设,即 Firebase Cloud Function 的每次运行都是独立的。

我觉得我在这里遗漏了一些非常明显的东西。有任何想法吗?

有问题的代码是:

exports.fillTemplate = functions.https.onCall(async (data, context) => {
    try {
        await downloadTemplateFile(data.docxTemplateDownloadUrl, localFilePath);
    } catch (e) {
        return buildErrorResponse('500', 'Unable to download file: ' + e);
    }

    var docx;
    try {
        docx = await readDocxFile(localFilePath);
     } catch (e) {
        console.log(e);
        return buildErrorResponse('500', 'Unable to interpret docx \' file: ' + e);
    }
    
    return buildSuccessResponse();
}

function readDocxFile(filePath) {
    try {
        var content = fs.readFileSync(filePath, 'binary');
        var zip = new PizZip(content);
        var iModule = inspectModule();
        var doc = new Docxtemplater(zip, { modules: [iModule] });
        return doc;
    } catch (e) {
        throw e;
    }
}

function downloadTemplateFile(downloadUrl, tmpFilePath) {
    axios({
        method: 'get',
        url: downloadUrl,
        responseType: 'stream',
    }).catch(function (error) {
        if (error.response) {
            console.log(error.response.data);
            console.log(error.response.status);
            console.log(error.response.headers);
        } else if (error.request) {
            console.log(error.request);
        } else {
            console.log('Error', error.message);
        }
        console.log(error.config);
        throw error;
    }).then(function (response) {
        console.log("Info: Received response for axios get");
        response.data.pipe(fs.createWriteStream(tmpFilePath));
        console.log("Info: Successfully wrote to " + tmpFilePath);
    });
}


       

标签: typescriptfirebaseasynchronousaxios

解决方案


推荐阅读