Преобразование потока в строку внутри функции обратного вызова для возврата строки

#javascript #node.js

#javascript #node.js

Вопрос:

Короче говоря: у меня есть функция обратного вызова, которая имеет строковый параметр и должна возвращать строку. Мне нужно преобразовать эту строку, используя библиотеку, которая работает только с потоками. Как мне это сделать?

Дольше: я использую Node.js replacestream, который имеет функцию для сопоставления с регулярным выражением и так же, как String.replace, позволяет указать функцию обратного вызова для замены. Что мне нужно сделать, это взять соответствующую строку, запустить ее через другую библиотеку, а затем вернуть преобразованную строку для замены.

Проблема в том, что эта библиотека работает только с потоками. Обычно я мог бы сделать все это асинхронным, но я не вижу никакого способа сделать это с помощью обратного вызова String.replace .

 src(['*.js'])
.pipe(replace(/`(.*?)`/gs, function(match, p1, offset, string) {
    var ostream = stringtostream(p1);
    ostream.pipe(glslminify());

    //???code that waits for ostream to finish and converts it to string???

    return string_from_ostream;
}))
.pipe(dest(jsdest));
  

Должен быть лучший способ сделать это, поэтому я ищу любые предложения.

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

1. Эта библиотека: github.com/TimvanScherpenzeel/glsl-minifier

2. Я смотрю… Он состоит из 4 разных вложенных библиотек, и по крайней мере у 2 из них есть способ сделать это синхронно, так что это полностью решило бы мою проблему, если бы все 4 из них могли это сделать.

3. К сожалению, этот кажется асинхронным: npmjs.com/package/glsl-min-stream

Ответ №1:

Вы пояснили, что библиотека использует поток и, что важно, выполняет свою работу асинхронно. Это означает, что вы не можете использовать его непосредственно в replace обратном вызове для определения возвращаемого значения обратного вызова, поскольку, конечно, это должно предоставляться синхронно.

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

Вот пример использования резервного асинхронного процесса, который сообщает о завершении с помощью обещаний (вы можете обернуть обещание вокруг потока или адаптировать код для использования завершения потока вместо этого):

 // Your function for processing the string
function yourFunction(str) {
    return Promise.all(
        str.split(/`(.*?)`/s).map((fragment, index) =>
            // The capture groups are the odd-numbered indexes
            index % 2 === 1
            ? process(fragment)
            : fragment
        )
    )
    .then(segments => segments.join(""));
}

// The promise wrapper around the library
function process(str) {
    return new Promise((resolve, reject) => {
        // Emulate via timer; I'm not emulating failure here, but
        // you'd handle failure by calling `reject`
        setTimeout(() => {
            // Success
            resolve(str.toUpperCase());
        }, Math.random() * 400);
    });
}

// Testing with and without leading and trailing text
yourFunction("`one two three` testing `two three four`")
.then(result => {
    console.log(result);
    return yourFunction("leading text `one two three` testing `two three four`")
})
.then(result => {
    console.log(result);
    return yourFunction("leading text `one two three` testing `two three four` trailing text")
})
.then(result => {
    console.log(result);
})
.catch(error => {
    // Handle/report error
});  

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

1. Спасибо, позвольте мне попытаться адаптировать это к моей конкретной ситуации, и после этого я отмечу ответ.