Node.js console.log - czy można zaktualizować linię zamiast tworzyć nową?


83

Moja node.jsaplikacja ma wiele dzienników konsoli, które są dla mnie ważne (jest to dość duża aplikacja, więc działa przez długi czas i muszę wiedzieć, że sprawy wciąż się rozwijają), ale kończę z tysiącami wierszy dzienniki konsoli.

Czy jest w jakiś sposób możliwe zrobienie a, console.updatektóre usuwa / zastępuje linię konsoli, zamiast tworzyć nową?


1
Dlaczego nie zapisać w pliku dziennika, który można monitorować lub przeszukiwać?
Nelson

1
Mogę to zrobić dość łatwo w PowerShell, ale bardziej chodzi o to, że mam około 5000 linii konsoli, które mogą z łatwością zająć 10 linii (większość z nich to tylko wywołania, które informują mnie, że sprawy postępują, co jest ważne, ponieważ aplikacja działa przez około 20 minut i potrzebuję informacji zwrotnej, czy coś się psuje / nadal działa).
JVG

Czy to odpowiada na twoje pytanie? Jak usunąć znaki wydrukowane w konsoli
Wex

Odpowiedzi:


127

Zamiast tego spróbuj grać metodami process.stdout na konsoli:

process.stdout.write("Hello, World");
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write("\n"); // end the line

10
TypeError: process.stdout.clearLine nie jest funkcją. Nie można uruchomić w burzy internetowej, jeśli ktoś inny to napotka.
Trevor

@TrevorD Moje podejście do tego polegało na dodaniu webstorm=trueparametrów aplikacji w konfiguracji węzła burzy internetowej i sprawdzeniu, czy process.argv.find(x => x.startsWith('webstorm=true')używa się tej odpowiedzi
Luiz Eduardo

1
@Luiz Eduardo Czy nie byłoby prościej po prostu zawinąć if (process.stdout.clearLine) { process.stdout.clearLine() }?
Trevor

Dobry chwyt! Z jakiegoś powodu nawet o tym nie pomyślałem. Ponieważ budowałem małe proste narzędzie do uruchamiania w konsoli, nie przeszedłem przez to dokładnie, ale na pewno je zmienię, dzięki!
Luiz Eduardo

Zrobiłbym to: node -e "for(let i=1;i<=1000;i++){process.stdout.write('Hello, World'); if(i<10)process.stdout.clearLine(); process.stdout.cursorTo(0);}"lubnode -e "for(let i=1;i<=1000;i++){process.stdout.clearLine(); process.stdout.cursorTo(0); process.stdout.write('hello, world')}"
Cerberus

55

Podążając za odpowiedzią @ michelek, możesz użyć funkcji podobnej do tej:

function printProgress(progress){
    process.stdout.clearLine();
    process.stdout.cursorTo(0);
    process.stdout.write(progress + '%');
}

1
Podczas używania tego z pętlą for miga, czy jest jakiś sposób, aby to naprawić?
Ank i zle

1
aby naprawić migotanie, pozbądź sięprocess.stdout.clearLine()
decoder7283

Zdałem sobie sprawę, że dodanie tego do dużej pętli drastycznie wydłuża czas obliczeń. Na przykład uruchamiam losowe próby 100 mil i przypisywanie do zmiennych. Powinno to zająć 3 sekundy. z tą funkcją. zajmuje to około minuty
Mj Jameel,

nieważne mój powyższy komentarz. Myślę, że wszystkie logi konsoli kosztują dużo. a ponieważ próbowałem wydrukować postęp w procentach, musiałem napisać funkcję, która drukuje tylko w określonych odstępach czasu, takich jak 1% 2% itd.
Mj Jameel

21

Jasne, możesz to zrobić za pomocą modułu, który pomogłem stworzyć: fknsrs / jetty

Zainstaluj przez

npm install jetty

Oto przykład użycia

// Yeah, Jetty!
var Jetty = require("jetty");

// Create a new Jetty object. This is a through stream with some additional
// methods on it. Additionally, connect it to process.stdout
var jetty = new Jetty(process.stdout);

// Clear the screen
jetty.clear();

// write something
jetty.text("hello world");
jetty.moveTo([0,0]);
jetty.text("hello panda");

Molo nie jest bardzo przydatne, gdy jest używane samodzielnie. Jest to o wiele bardziej efektywne, gdy tworzysz na niej jakąś abstrakcję, aby wywołania na molo były mniej szczegółowe.


3
Głosowałem w dół z powodu restrykcyjnej licencji na ten pakiet.
mmmeff

17
Jest to standardowa 3-klauzula licsense BSD . Całkiem zły powód do przegłosowania, imo.
Dziękuję

6
@mmmeff, jeśli uważasz, że 3-klauzula BSD licencja jest restrykcyjna, obawiam się, że umrzesz, gdy usłyszysz o licencjach GPL i AGPL.
Michael Pfaff

15

Napisanie częściowej linii.

process.stdout.write("text");
process.stdout.write("more");
process.stdout.write("\n"); // end the line

Jeśli wielkość danych wyjściowych jest prawdziwym problemem, prawdopodobnie przemyślisz swoje logowanie. Możesz użyć systemu rejestrowania, który umożliwia selektywne rejestrowanie w czasie wykonywania, aby zawęzić dane wyjściowe do tego, czego potrzebujesz.

// The sections we want to log and the minimum level
var LOG_LEVEL = 4;
var LOG_SECTIONS = ["section1","section2","section3"];

function logit(msg, section, level) {
  if (LOG_SECTIONS.indexOf(section) > -1 && LOG_LEVEL >= level) {
    console.log(section + ":" + msg);
  }
}

logit("message 1", "section1", 4); // will log
logit("message 2", "section2", 4); // will log
logit("message 3", "section3", 2); // wont log, below log level
logit("message 4", "section4", 4); // wont log, not in a log section

6

Po prostu użyj \ r, aby zakończyć linię:

process.stdout.write('text\r');

Oto prosty przykład (zegar ścienny):

setInterval(() => process.stdout.write(`clock: ${new Date()}\r`), 1000);

To działa, ale jeśli „zmieniona” linia jest krótsza niż poprzednia, zachowa niektóre stare znaki w terminalu.
Matthijn

5

Jeśli widzisz wyjątki stdout, takie jak TypeError: process.stdout.clearLine is not a functionw oknie konsoli debugowania programu Visual Studio Code (lub burzy internetowej), uruchom aplikację jako zewnętrzną aplikację terminala zamiast wewnętrznej konsoli. Powodem jest to, że okno konsoli debugowania nie jest TTY ( process.stdout.isTTYjest fałszywe). Dlatego zaktualizuj konfigurację uruchamiania za launch.jsonpomocą "console": "externalTerminal"opcji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.