Перезапись нескольких предыдущих выходов терминала

У меня есть прокси-сервер webpack-dev-server, и я хочу отображать запросы к прокси в окне терминала во время работы сервера. Что усложняет это, так это то, что я хочу отображать запрос при его получении, а затем обновлять то, что было первоначально написано после получения ответа, с кодом состояния. Например, если бы я запросил GET /foo, я бы хотел, чтобы это изначально отображалось:

(---) GET /foo

Затем, если прокси-сервер возвращает статус ответа 200, я хочу обновить вывод консоли следующим образом:

(200) GET /foo

У меня это (в основном) работает с этим:

const readline = require('readline');
// ...
devServer: {
    proxy: {
        onProxyReq: function (proxyReq, req, res) {
            process.stdout.write(`(---) ${req.method} ${req.url}`);
            proxyReq.on('response', function(response) {
                readline.clearLine(process.stdout, 0);
                readline.cursorTo(process.stdout, 0, null);
                process.stdout.write(`(${response.statusCode}) ${req.method} ${req.url}\n`);
            });
        }
    }
}
// ...

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

(---) GET /foo/1(---) GET /bar/2(---) GET /baz/3
(200) GET /bar/2
(200) GET /baz/3
(200) GET /foo/1

Я смотрел на использование readline's moveCursor против cursorTo, но я не знаю, как отследить, какой номер строки был написан ранее.

Как я могу изменить то, что у меня есть, чтобы отслеживать и перезаписывать правильную строку вывода консоли при получении ответа?

1 ответ

Решение

Я думаю, что вам нужно использовать readline.moveCursor чтобы переместить курсор относительно его текущей позиции, вернитесь к строке, соответствующей запросу. Это также означает, что вам нужно отслеживать текущую строку или всегда возвращать ее к x: 0 после каждой записи.

Следующий фрагмент не совсем то, что вы ищете, но он демонстрирует, как использовать команды курсора readline, чтобы перезаписывать существующий вывод консоли с течением времени.

const readline = require('readline')

let i = 0;
const next = () => {
    if (i && i%3 === 0) readline.moveCursor(process.stdout, null, -3)
    readline.cursorTo(process.stdout, 0, null);
    readline.clearLine(process.stdout, 0);
    process.stdout.write(`${i}\n`);
    i += 1;
    if (i < 9) setTimeout(next, 200);
    else console.log();
}
setTimeout(next, 200);

Для вашего конкретного примера, я думаю, вы хотите что-то более похожее на следующее:

const readline = require('readline');
// ...
urls = [];
const rowOf = url => {
    let row = urls.indexOf(req.url);
    if (row === -1) {
        row = urls.length;
        urls.push(req.url);
    }
    return row;
}

const writeLine = (row, str) => {
    readline.moveCursor(process.stdout, null, row);
    readline.cursorTo(process.stdout, 0, null);
    readline.clearLine(process.stdout, 0);
    process.stdout.write(str);
    readline.moveCursor(process.stdout, null, -1*row);
    readline.cursorTo(process.stdout, 0, null);
}

devServer: {
    proxy: {
        onProxyReq: function (proxyReq, req, res) {
            writeLine(rowOf(req.url), `(---) ${req.method} ${req.url}`);
            proxyReq.on('response', function(response) {
                writeLine(rowOf(req.url), `(${response.statusCode}) ${req.method} ${req.url}\n`)
            });
        }
    }
}
Другие вопросы по тегам