Here is an approach that's uses a nice feature of modern JS.  Generators..
Using generators you can create composable code.  Instead of creating 1 function that does this one specific thing, you can compose a function than stream together multiple generators.  This is great for making re-usable code.
Below I've created 3 function,.
- randomValues => this just generates random number between a range.
- repeatLimit => this generator just prevents x amount of repeated values
- iterCount => this generator stop after count iterations
All you do then is compose all these generators together, but the bonus is that these generators can be used in other places.  eg.  [...repeatLimit(3, [1,1,1,1, 0,0,0,0])] would return 1,1,1,0,0,0.
function* randValues(min, max) {
  const range = max - min;
  while (true) 
    yield min + Math.trunc(Math.random() * range);
}
function* repeatLimit(limit, gen) {
  let rcount = 0, rvalue;
  for (let g of gen) {
    if (rvalue === g) rcount += 1; else rcount = 1;
    rvalue = g;
    if (rcount <= limit) yield g;
  }  
}
function* iterCount(count, gen) {
  for (let g of gen) {
    yield g;
    count --;
    if (count <= 0) break;
  }
}
const gen = 
  iterCount(22, repeatLimit(3, randValues(0, 2)));
for (const r of gen) {
  console.log(r);
}