@Bigma said in Комменты в js // не нравятся басу:
вот об эту скобку бас споткнется, но даже кубик не покажет какой, ищи потом по всему скрипту.
Да прикольный баг, я как-то ловил подобные. Много нервных клеток забирают ))
Приветствую!
Подскажите пожалуйста что может быть?
Есть Поток 1 в нем вызываю асинхронную функцию, а в ней есть код написан на node.js
когда выполняется этот код, зависает основной поток. Но результат я получаю но в моменте выполнения висит поток 1 а потом крашиться..
Версия BAS 28.1.2 версия Node.js v22.11.0
Большое спасибо за ответы или советы!
const fs = require("fs").promises;
const path = require("path");
const encoding = require("encoding");
const { MongoClient } = require("mongodb");
const crypto = require("crypto");
// Импортируем функцию для подключения к базе данных
const getConnect = require("../connectDB");
// Конфигурационные параметры
const MONGOSERVER = process.env.MONGOSERVER || [[MONGOSERVER]];
const DATABASE = process.env.DATABASE || [[DATABASE]];
const PATCHCRONAS_BASE = process.env.PATCHCRONAS_BASE || [[PATCHCRONAS]];
const SESSION_ID = process.env.SESSION_ID || [[SESSION_ID]];
const PATCHCRONAS = path.join(PATCHCRONAS_BASE, "out", SESSION_ID);
const folderPath = path.join(PATCHCRONAS, `${SESSION_ID}_files`);
const filePath = path.join(PATCHCRONAS, `${SESSION_ID}.txt`);
/**
* Асинхронно ожидает появления файла в течение заданного таймаута.
* @param {string} filePath - Полный путь к файлу.
* @param {number} timeout - Таймаут в миллисекундах.
* @param {number} pollInterval - Интервал проверки в миллисекундах.
* @returns {Promise<string>} - Возвращает путь к файлу, если он появляется вовремя.
* @throws {Error} - Если файл не появляется в течение таймаута.
*/
async function waitForFile(filePath, timeout = 5 * 60 * 1000, pollInterval = 1000) {
return new Promise((resolve, reject) => {
const startTime = Date.now();
const interval = setInterval(async () => {
try {
await fs.access(filePath);
clearInterval(interval);
resolve(filePath);
} catch (err) {
if (Date.now() - startTime > timeout) {
clearInterval(interval);
reject(new Error("Файл не появился в течение 5 минут."));
}
// Файл ещё не существует, продолжаем ожидание
}
}, pollInterval);
});
}
/**
* Сохраняет HTML-контент в базу данных MongoDB.
* @param {string} sessionId - Идентификатор сессии.
* @param {string} sectionName - Название секции.
* @param {string} htmlContent - HTML-содержимое.
*/
async function saveToDatabase(sessionId, sectionName, htmlContent) {
try {
const client = await getConnect(MONGOSERVER);
const database = client.db(DATABASE);
await database.collection("reports").findOneAndUpdate(
{ sessionId },
{
$push: {
sections: {
name: sectionName,
htmlContent,
hasData: true,
},
},
$set: { updatedAt: new Date() },
},
{ returnDocument: "after", upsert: true }
);
await client.close();
} catch (error) {
console.error("Ошибка при сохранении данных в базу:", error.message);
}
}
/**
* Вычисляет SHA-256 хэш файла асинхронно.
* @param {string} filePath - Путь к файлу.
* @returns {Promise<string|null>} - Возвращает хэш или null в случае ошибки.
*/
async function getFileHash(filePath) {
try {
const fileBuffer = await fs.readFile(filePath);
const hashSum = crypto.createHash("sha256");
hashSum.update(fileBuffer);
return hashSum.digest("hex");
} catch {
return null;
}
}
/**
* Извлекает имена файлов изображений из текста.
* @param {string} text - Входной текст.
* @returns {string[]} - Массив имен файлов изображений.
*/
function extractImageFilenames(text) {
const pattern = /Cro[A-Za-z0-9]{2,7}\.(jpg|png)/gi;
return text.match(pattern) || [];
}
/**
* Удаляет дубликаты изображений по хэшу асинхронно.
* @param {string[]} imageFilenames - Имена файлов изображений.
* @param {string} folderPath - Путь к папке с изображениями.
* @returns {Promise<number>} - Количество удалённых дубликатов.
*/
async function removeDuplicateImagesInOrder(imageFilenames, folderPath) {
const imageHashes = new Map();
let duplicatesRemoved = 0;
for (const fileName of imageFilenames) {
const filePath = path.join(folderPath, fileName);
try {
await fs.access(filePath);
} catch {
continue; // Файл не существует
}
const fileHash = await getFileHash(filePath);
if (!fileHash) continue;
if (imageHashes.has(fileHash)) {
try {
await fs.unlink(filePath);
duplicatesRemoved++;
} catch (err) {
console.error(`Не удалось удалить файл ${filePath}:`, err.message);
}
} else {
imageHashes.set(fileHash, fileName);
}
}
return duplicatesRemoved;
}
/**
* Заменяет имена файлов изображений в тексте на встроенные изображения в формате base64.
* @param {string} inputText - Входной текст.
* @param {string} folderPath - Путь к папке с изображениями.
* @returns {string} - Обработанный текст с встроенными изображениями.
*/
async function replaceImagesInText(inputText, folderPath) {
let text = inputText;
const pattern = /Cro[A-Za-z0-9]{2,7}\.(jpg|png)/gi;
const matches = text.match(pattern);
if (!matches) return text;
for (const fileName of matches) {
const filePath = path.join(folderPath, fileName);
try {
await fs.access(filePath);
const fileBuffer = await fs.readFile(filePath);
const base64Data = fileBuffer.toString("base64");
const mimeType = fileName.endsWith(".png") ? "image/png" : "image/jpeg";
const imgTag = `<div class="photo-container"><img src="data:${mimeType};base64,${base64Data}" alt="${fileName}"></div>`;
const regex = new RegExp(fileName, "g");
text = text.replace(regex, imgTag);
} catch {
// Удаляем строку с отсутствующим изображением
const regex = new RegExp(`.*${fileName}.*\n?`, "gi");
text = text.replace(regex, "");
}
}
return text;
}
/**
* Получает MIME-тип файла по расширению.
* @param {string} filePath - Путь к файлу.
* @returns {string} - MIME-тип файла.
*/
function getMimeType(filePath) {
const ext = path.extname(filePath).toLowerCase();
switch (ext) {
case ".jpg":
case ".jpeg":
return "image/jpeg";
case ".png":
return "image/png";
default:
return "application/octet-stream";
}
}
/**
* Очищает и форматирует текст.
* @param {string} inputText - Входной текст.
* @returns {string} - Очищенный и отформатированный текст.
*/
function cleanText(inputText) {
let cleanedText = inputText
.replace(/[-]/g, "")
.replace(/[ \t]+/g, " ")
.replace(/ *\n */g, "\n")
.replace(/\n{2,}/g, "\n")
.trim();
const photosLinePattern = /(^|\n)\s*Фото:\s*(\n|$)/gi;
cleanedText = cleanedText.replace(photosLinePattern, "");
cleanedText = cleanedText.replace(/Ответ № (\d+)/g, "Лок № $1");
const lines = cleanedText.split("\n");
const uniqueLines = [];
lines.forEach((line, index) => {
const currentLine = line.trim().toLowerCase();
const previousLine = index > 0 ? lines[index - 1].trim().toLowerCase() : null;
if (index === 0 || currentLine !== previousLine) {
uniqueLines.push(line);
}
});
return uniqueLines.join("<br>");
}
/**
* Обрабатывает текст и изображения, а затем сохраняет результаты в базу данных.
* @param {string} inputText - Входной текст.
* @param {string} folderPath - Путь к папке с изображениями.
* @param {string} sessionId - Идентификатор сессии.
*/
async function processTextAndImagesToDatabase(inputText, folderPath, sessionId) {
try {
const cleanedText = cleanText(inputText);
const imageFilenames = extractImageFilenames(inputText);
const folderExists = await fs.access(folderPath).then(() => true).catch(() => false);
if (folderExists) {
const duplicatesRemoved = await removeDuplicateImagesInOrder(imageFilenames, folderPath);
console.log(`Удалено ${duplicatesRemoved} дубликатов изображений.`);
}
const finalText = await replaceImagesInText(cleanedText, folderPath);
const htmlContent = `
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Отчет</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
}
.photo-container {
margin: 10px 0;
}
.photo-container img {
max-width: 100%;
height: auto;
display: block;
}
</style>
</head>
<body>
${finalText}
</body>
</html>
`;
await saveToDatabase(sessionId, "cas", htmlContent);
console.log("Данные успешно сохранены в базу данных.");
} catch (error) {
console.error("Ошибка обработки текста и изображений:", error.message);
}
}
/**
* Основная функция обработки.
*/
async function main() {
try {
console.log("Ожидание появления файла...");
await waitForFile(filePath);
console.log("Файл обнаружен.");
// Читаем файл как Buffer
const fileBuffer = await fs.readFile(filePath);
// Конвертация из Windows-1251 в UTF-8
const convertedContent = encoding.convert(fileBuffer, "UTF-8", "WINDOWS-1251").toString();
// Перезаписываем файл уже в UTF-8 (опционально, если необходимо)
await fs.writeFile(filePath, convertedContent, "utf8");
console.log("Файл успешно прочитан и преобразован.");
// Обрабатываем текст и изображения, сохраняем в базу данных
await processTextAndImagesToDatabase(convertedContent, folderPath, SESSION_ID);
} catch (err) {
console.error("Ошибка при обработке файла:", err.message);
}
}
// Запуск основной функции
main();