I'm trying to update console log lines when using nodejs readline and process.stdout rather than reprinting the logs repeatedly.
const readline = require('readline')
let firstLog = true;
/**
* BEGIN Helper Functions
*/
function randomIntFromInterval(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min)
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
function concurrency(array, map, limit) {
let arr = [...array]
let pendingCount = 0
const results = []
return new Promise((resolve, reject) => {
function pump() {
while (arr && arr.length && pendingCount < limit) {
pendingCount++
map(arr.shift(), pendingCount).then(
(result) => {
pendingCount--
results.push(result)
pump()
},
(err) => {
arr = null
reject(err)
},
)
}
if (!pendingCount) {
return resolve(results)
}
}
pump()
})
}
/**
* END Helper Functions
*/
const data = [];
/**
* Seed test data
*/
for (let i = 0; i < 10; i++) {
const item = {
name: i.toString(),
status: 'initialized'
};
data.push(item)
log(item)
}
/**
* Process all items concurrently
* @param {*} item
*/
function main() {
concurrency(data, async (item ,i) => {
await updateStatusAsync(item)
log(item, i)
}, 3)
}
/**
* Update status while simulating long running task
* @param {*} repo
*/
async function updateStatusAsync(item) {
await sleep(randomIntFromInterval(3, 5) * 1000)
item.status = "completed"
}
function log(item, i) {
if (i > 0 && firstLog) {
i--
readline.moveCursor(process.stdout, 0, -(data.length - i))
readline.cursorTo(process.stdout, 0)
firstLog = false
}
readline.clearLine(process.stdout)
process.stdout.write(`${item.name}: ${item.status}\n`)
}
main()
The code above will log all items in an array and then at random intervals, each status field will be updated to reflect a new value.
Initially all are in initialized state:
0: initialized
1: initialized
2: initialized
3: initialized
4: initialized
...
It will then update at random intervals to completed.
How can I update each line item "in-place" rather than having to re-print all of them every time an item updates?