# #typescript #firebase #asynchronous #axios
Вопрос:
Я пишу облачную функцию Firebase, которая загружает файл, записывает его в /tmp/, а затем пытается проанализировать его как файл Docx с помощью пакета docxtemplater. Я намерен еще немного обработать этот файл, как только он будет запущен и запущен, но это к делу не относится.
Моя проблема то, что я написал до сих пор, обычно работает, в то время как в других случаях я получаю следующую ошибку:
`Error: ENOENT: no such file or directory, open '/tmp/template_file'`
Когда появляется эта ошибка, повторный запуск функции, как правило, просто устранит проблему и начнет возвращать успехи. Затем я могу спамить функцию, и в итоге у меня будет куча разных успехов без сбоев. Это заставляет меня подозревать две проблемы:
- Мой код неправильно обрабатывает асинхронные части axios get, write и read.
- Странное поведение кэширования происходит с функциями 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. Это было как раз по деньгам. Очень признателен.