Машинопись: Проблемы асинхронности при получении, записи и чтении файлов axios

# #typescript #firebase #asynchronous #axios

Вопрос:

Я пишу облачную функцию Firebase, которая загружает файл, записывает его в /tmp/, а затем пытается проанализировать его как файл Docx с помощью пакета docxtemplater. Я намерен еще немного обработать этот файл, как только он будет запущен и запущен, но это к делу не относится.

Моя проблема то, что я написал до сих пор, обычно работает, в то время как в других случаях я получаю следующую ошибку:

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

Когда появляется эта ошибка, повторный запуск функции, как правило, просто устранит проблему и начнет возвращать успехи. Затем я могу спамить функцию, и в итоге у меня будет куча разных успехов без сбоев. Это заставляет меня подозревать две проблемы:

  1. Мой код неправильно обрабатывает асинхронные части axios get, write и read.
  2. Странное поведение кэширования происходит с функциями Firebase. С другой стороны, вполне возможно, что (1) здесь полностью виноват. Другими словами, при первом запуске кода чтение файла происходит до завершения начальной загрузки (не совсем понятно, почему это происходит-возможно, я злоупотребляю ожиданием / обещаниями?), В то время как последующие запуски функций завершаются успешно, потому что файл уже загружен. С другой стороны, если бы это было правдой, это противоречило бы моему предположению о том, что каждый запуск облачной функции Firebase независим.

Я чувствую, что упускаю здесь что-то очень очевидное. Есть какие-нибудь идеи?

Код, о котором идет речь, является:

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


       

 

Комментарии:

1. await downloadTemplateFile(data.docxTemplateDownloadUrl, localFilePath); похоже, это указывает на то, что downloadTemplateFile функция возвращает обещание. Однако… внимательно изучите свой код. На самом downloadTemplateFile деле в нем отсутствует оператор return, поэтому он неявно возвращается undefined (и, кроме того, из-за этого не ждет завершения процесса, который он запускает).

2. Это было как раз по деньгам. Очень признателен.