Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Асинхронная функция в replace возвращает описание промиса (https://javascript.ru/forum/misc/85921-asinkhronnaya-funkciya-v-replace-vozvrashhaet-opisanie-promisa.html)

Steh 29.05.2024 14:00

Асинхронная функция в replace возвращает описание промиса
 
Асинхронная функция в replace выводит в консоль нормальные резы, а возвращает [object Promise]

Такое впечатление, что не дожидается результата. Почему так? Без функции срабатывает нормально, например, когда меняешь на результат асинхронного чтения. Получается функция в функции, из-за этого какие-то баги. Такое бывает в алерте с объектами, пробовал приводить к строке, не помогает.

Nexus 29.05.2024 14:39

Ничего не понял, но очень интересно. ©
Без кода сложно сказать что вы делаете неправильно.

[object Promise] - результат приведения промиса к строке.

Steh 29.05.2024 14:50

replace(/.../, async () => await fs.promises.readFile...
когда console.log , норм резы, а с return заменяет на канитель

Nexus 29.05.2024 14:52

Steh, где вы взяли функцию replace?
Вы уверены, что она может принимать вторым аргументом Promise?

Может стоит попробовать так?
readFile.then(content => replace(/../, content)).then(console.log);

Steh 29.05.2024 14:55

попробую с обычным чтением

Steh 29.05.2024 15:26

я хочу попробовать в одну строчку, разделю сейчас

cont=(await readFile('layout.html','utf8'))

.replace('{% get title %}', await readFile(rqu+'title.html','utf8'))
.replace('{% get content %}',await readFile(rqu+'content.html','utf8'))
.replace('{% key %}',await readFile(rqu+'key.html','utf8'))
.replace('{% desc %}',await readFile(rqu+'desc.html','utf8'))

.replace(/{% get elem (\w+?) %}/g, async (a, b) =>await readFile(rqu+'elem/' + b + '.html', 'utf8'));


подводит последний фрагмент

voraa 29.05.2024 16:07

Не, так просто тут не сделать.
Последняя строчка не пройдет.
Попробуйте вместо нее такой код
const matchs = cont.matchAll(/{% get elem (\w+?) %}/g);
for (const m of matchs) {
	cont = cont.replace(m[1], await readFile(rqu+'elem/' + m[2] + '.html', 'utf8')
}

Steh 29.05.2024 16:18

спасибо за совет, через match могу сделать, интересовала причина. Ну, видимо, так устроено

voraa 29.05.2024 16:43

Цитата:

Сообщение от Steh
Ну, видимо, так устроено

Конечно. В данном случае задается cfllback функция, которая будет, когда надо, вызываться из функции replace. И вызываться она будет без await. И возвращать не строку, а промис.

Aetae 29.05.2024 21:37

Если ты в ноде, то можешь использовать readFileSync, хотя это и не рекомендуется.

Реплейсить в несколько проходов в любом случае - не стоит. По простому я бы сделал arr = base.split(/\{% (.*?) %\}/g) и проход через for(let i=1; i < arr.length; i+=2) { ... }.

Ну и в принципе если ты свой шаблонизатор пишешь который в теории будет усложняться, то лучше сразу без регулярок обойтись - "по взрослому" делать ast и\или конечный автомат.:)

Alexandroppolus 29.05.2024 21:38

Цитата:

Сообщение от voraa
cont = cont.replace(m[1]

в общем случае так нельзя. Во первых, регулярка может быть с lookahead/lookbehind, во вторых, вторая замена пойдет по ранее замененному тексту и может что-то поправить в контенте, который был вставлен.

надо пройтись регуляркой, порезать текст на куски (матчи и то что между ними), для матчей загрузить асинхронный контент, заменить им соответствующие куски, и сделать join

пример сразу на тайпскрипте

если надо js, просто выкинь типы


Часовой пояс GMT +3, время: 04:59.