# Best way to slow down generators?

**URL:** <https://talk.observablehq.com/t/best-way-to-slow-down-generators/180>\
**Category:** Uncategorized\
**Created:** [February 1, 2018, 6:05pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180 "2018-02-01T18:05:18Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![nstrayer](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nstrayer/32/126_2.png) [@nstrayer](https://talk.observablehq.com/u/nstrayer)\
**Post date:** [February 1, 2018, 6:05pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/1 "2018-02-01T18:05:19Z")

</div>

So in a notebook I want debug some code in a generator cell.

Say I have a loop like

```auto
{
     for(let i=0;i<10;i++){
       yield i;
     }
}

```

This is great for seeing what’s going on but javascript is too fast! I want to slow it down so I can see the loop step through but when I throw in a timeout or something with await to force stopping I get the error “async not allowed in generators”.

Whats the best way of going about slowing down execution of a generator in this way?

---

<div class="post-metadata">

**Author:** ![jashkenas](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jashkenas/32/1778_2.png) [@jashkenas](https://talk.observablehq.com/u/jashkenas)\
**Post date:** [February 1, 2018, 6:13pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/2 "2018-02-01T18:13:28Z")

</div>

Give this a try:

```auto
{
  for (let i=0;i<10;i++) {
    yield Promises.delay(1000, i);
  }
}

```

For more, see:

[https://beta.observablehq.com/@mbostock/standard-library](https://beta.observablehq.com/@mbostock/standard-library)

---

<div class="post-metadata">

**Author:** ![nstrayer](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nstrayer/32/126_2.png) [@nstrayer](https://talk.observablehq.com/u/nstrayer)\
**Post date:** [February 1, 2018, 6:30pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/3 "2018-02-01T18:30:47Z")

</div>

> [@jashkenas](#):
>
> yield Promises.delay(1000, i);

Worked beautifully, thanks a ton! The ability to throw `yields` into intermediate stages makes debugging a dream!

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [February 1, 2018, 7:46pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/4 "2018-02-01T19:46:47Z")

</div>

And if you want multiple cells to be precisely synchronized, try Promises.tick instead of Promises.delay:

```auto
{
  for (let i = 0; i < 10; ++i) {
    yield Promises.tick(1000, i);
  }
}

```

---

<div class="post-metadata">

**Author:** ![nstrayer](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nstrayer/32/126_2.png) [@nstrayer](https://talk.observablehq.com/u/nstrayer)\
**Post date:** [February 1, 2018, 8:09pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/5 "2018-02-01T20:09:49Z")

</div>

Cool! I’m assuming that one is based on `requestAnimationFrame` instead of a timeout?

---

<div class="post-metadata">

**Author:** ![mbostock](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mbostock/32/9_2.png) [@mbostock](https://talk.observablehq.com/u/mbostock)\
**Post date:** [February 1, 2018, 8:14pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/6 "2018-02-01T20:14:38Z")

</div>

Promises.delay, Promises.tick and Promises.when all use setTimeout because typically you want to sleep for longer than one animation frame. If you just want to sleep for one animation frame, then `yield` without any promise is the simplest option:

```auto
{
  for (let i = 0; i < 10; ++i) {
    yield i;
  }
}

```

What makes Promises.tick synchronized is that it uses Promises.when under the hood, which allows multiple promises that want to wake up at the same time to use the same setTimeout internally:

> <https://github.com/observablehq/notebook-stdlib/blob/master/src/promises/when.js>

---

<div class="post-metadata">

**Author:** ![danbri](https://avatars.discourse-cdn.com/v4/letter/d/e99b99/32.png) [@danbri](https://talk.observablehq.com/u/danbri)\
**Post date:** [October 16, 2021, 9:18am UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/7 "2021-10-16T09:18:21Z")

</div>

Can these ideas be applied to case where you want to periodically sample from an underlying fast generator?

e.g. to update ui that is more sensibly updated at 1 fps rather than 60 fps.

Unlike in the above example I don’t want to slow down the underlying computation, just stream regular snapshots

---

<div class="post-metadata">

**Author:** ![danbri](https://avatars.discourse-cdn.com/v4/letter/d/e99b99/32.png) [@danbri](https://talk.observablehq.com/u/danbri)\
**Post date:** [October 16, 2021, 2:13pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/8 "2021-10-16T14:13:10Z")

</div>

Blundered my way to this via the Custom Generators writeup,

slowloop = {  
let i = 0,  
looper;  
let slowcoreloop = runSimulation(osc2NodeExample());  
for await (looper of slowcoreloop) {  
yield { count: i, main: looper };  
i++;  
await Promises.delay(500);  
}  
}

Where async function\* runSimulation(net) {…etc defines (if I have my terminology right) the generator function. I had trouble using a generator instantiated already in another cell, but this is progress at least…

---

<div class="post-metadata">

**Author:** ![danbri](https://avatars.discourse-cdn.com/v4/letter/d/e99b99/32.png) [@danbri](https://talk.observablehq.com/u/danbri)\
**Post date:** [October 16, 2021, 6:07pm UTC](https://talk.observablehq.com/t/best-way-to-slow-down-generators/180/9 "2021-10-16T18:07:48Z")

</div>

~~cleaned up a bit,~~

Playing with variations, … but this isn’t quite right either

…  
while (true) {  
if (coreloop.count % 10 == 0) {  
yield coreloop;  
}

~~await Promises.delay(1000);  
}~~
