Кластер Node.js; перемешанный вывод на консоль ТОЛЬКО при использовании цвета

Н ello! Я запускаю проект кластеризованных узлов с несколькими узлами. Они делают довольно много консольного вывода. Я также хочу быть в состоянии сделать красивый цветной вывод.

Моя проблема: я получаю беспорядочный вывод на консоль гонки-условия ТОЛЬКО ПРИ ИСПОЛЬЗОВАНИИ ЦВЕТОВ.

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

let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let getMyUniqueString = () => {
  return chars[Math.floor(Math.random() * chars.length)].repeat(100);
};

Я запускаю несколько узлов, которые используют эту функцию, чтобы определить их уникальные строки, и вижу что-то вроде следующего:

Консольный вывод без каких-либо помех

Разве это не красиво! Независимо от того, как долго и как яростно выводятся все эти узлы, этот вывод консоли никогда не будет перемешан.

Теперь я попробую с уникальными строками, которые содержат лишь немного цвета:

let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let getMyUniqueString = () => {
  let redEscSeq = '\x1b[41m';
  let clearEscSeq = '\x1b[0m';
  let aRedBoxOfText = redEscSeq + '  ' + clearEscSeq;
  let repeatedChars = chars[Math.floor(Math.random() * chars.length)].repeat(100);
  return aRedBoxOfText + repeatedChars;
};

И посмотрите, как печально выглядят некоторые из моих результатов!

Единственный способ передачи данных на терминал через все узлы - через console.log функция.

Почему console.log достаточно умен, чтобы сохранить вывод многих узлов без искажений, когда нет цвета, но не достаточно умен, чтобы сделать это, когда даже немного цвета включено??

Спасибо за любую помощь!

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

РЕДАКТИРОВАТЬ: Хотя эта проблема существует в собственной консоли windows "cmd.exe", в консоли powershell и в ConEmu (симпатичный сторонний терминал Windows, показанный на снимках экрана), она НЕ существует в терминале Cygwin! В Cygwin никогда не бывает помех, даже с тоннами цветов и асинхронным выходом. Что я могу сделать, чтобы поощрить это поведение Cygwin в других консолях?

1 ответ

Решение

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

Хотя сам Windows API фактически поддерживает печать разноцветной строки в одном вызове API, как показано здесь: https://docs.microsoft.com/en-us/windows/console/writeconsoleoutput, где каждый символ содержит информацию о цвете, Но он также не поддерживает управляющие коды ANSI. И это не то, что на самом деле используется JavaScript.

Движок Nodejs использует библиотеку libuv для записи строк в терминал, которая является кроссплатформенной и внутренне транслирует управляющие коды ANSI для правильной работы. Но если вы внимательно посмотрите на источник libuv для обработки escape-кодов ANSI, вы увидите, что он выполняет полную очистку буфера после каждого escape-кода, что означает, что в какой-то момент он должен стать множественными вызовами API Windows для печати одной строки текста.

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

Таким образом, ответ здесь заключается в том, что нет решения. Или вы соглашаетесь с использованием Cygwin в качестве решения.

Другие вопросы по тегам