# Wait or delay into Loop

**URL:** <https://discourse.processing.org/t/wait-or-delay-into-loop/31468>\
**Category:** Coding Questions\
**Tags:** homework\
**Created:** [July 27, 2021, 9:37pm UTC](https://discourse.processing.org/t/wait-or-delay-into-loop/31468 "2021-07-27T21:37:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Eddie\_float](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/eddie_float/32/13973_2.png) [@Eddie\_float](https://discourse.processing.org/u/Eddie_float)\
**Post date:** [July 27, 2021, 9:37pm UTC](https://discourse.processing.org/t/wait-or-delay-into-loop/31468/1 "2021-07-27T21:37:43Z")

</div>

I want to create a pause, wait or delay inside the loops. Is this possible?

![1](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/5/51113d4876601c4fe23a724cf1c58cbe9390232d.png)

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [July 27, 2021, 10:09pm UTC](https://discourse.processing.org/t/wait-or-delay-into-loop/31468/2 "2021-07-27T22:09:34Z")

</div>

when you want to see the animation (ellipses appearing slowly) this delay won’t help you, because draw() updates the screen only at the end and not throughout.

Hence you need to get rid of the for-loops and use the fact that draw() repeats itself automatically 60 times per second.

In my example the delay is done by frameRate but you can search millis() or timer here on the forum for a timer. The command delay() is not useful here.

Please remember to post your code as text not as image.

Chrisir

**Example**

```auto

int x=20; 
int y=20;

void setup() {
  size(600, 600);
  frameRate(2);
}

void draw() {
  ellipse(x, y, 40, 40); 

  y += 40; 

  if (y>=height) {
    x+=40;
    y=20;
  }
}

```

---

<div class="post-metadata">

**Author:** ![KumuPaul](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kumupaul/32/13072_2.png) [@KumuPaul](https://discourse.processing.org/u/KumuPaul)\
**Post date:** [July 27, 2021, 10:11pm UTC](https://discourse.processing.org/t/wait-or-delay-into-loop/31468/3 "2021-07-27T22:11:39Z")

</div>

In theory there are several ways to introduce a wait/delay into the draw function.

### 1. Using async/await

```auto
function setup() {
  createCanvas(400, 400);
  frameRate(1);
}

async function draw() {
  background(220);
  for (let i = 0; i < 10; i++) {
    circle(random(0, width), random(0, height), 20);
    await delay(500);
  }
}

function delay(ms) {
  return new Promise(done => setTimeout(done, ms));
}

```

Technically this does introduce a delay, and when draw is called one circle will be drawn every 1/2 second. However p5.js ignores the return value from draw and doesn’t know that it should wait for the Promise that is implicitly returned due to the use of `async` before calling `draw()` again. So if you run this you will see that more an more circles keep getting added because you end up with many instances of `draw()` running simultaneously. You could improve the behavior of this approach by calling `noLoop()` in your setup and then calling `redraw()` after your for loops exit:

```auto
function setup() {
  createCanvas(400, 400);
  noLoop();
}

async function draw() {
  background(220);
  for (let i = 0; i < 10; i++) {
    circle(random(0, width), random(0, height), 20);
    await delay(500);
  }
  redraw();
}

function delay(ms) {
  return new Promise(done => setTimeout(done, ms));
}

```

This is actually a pretty good result.

### 2. “busy wait” in draw()

You really don’t want to do this, but I just want to document that fact. This code blocks the `draw()` function for 500 milliseconds per circle drawn:

```auto
function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  for (let i = 0; i < 10; i++) {
    circle(random(0, width), random(0, height), 20);
    delay(500);
  }
}

function delay(ms) {
	let t = new Date().getTime();
	while (new Date().getTime() - t < (ms || 0)) {
		// busy wait
	}
}

```

The problem here is that because of the single threaded nature of JavaScript, if you’ve got the main thread busily “delaying” in your `draw()` function in between “drawing” each circle, the browser actually never gets a chance to display the stuff that you are “drawing” to the canvas (when you call a function like `circle()` it doesn’t actually immediately display the circle, you can basically think of it as queuing the circle to be displayed once the `draw()` function exits, or drawing the circle to an off screen buffer that is not actually painted onto the screen until the `draw()` function exits.

The result of running this code will be 1) your browser tab becomes mostly unresponsive, 2) your CPU usage spikes, and 3) the set of 10 circles will all be displayed at once at every 5 seconds or so.

### 3. Using a generator function

Lastly, this is a bit more advanced, but you could put your drawing sequence into a type of function called a generator function that returns an iterator:

```auto
const delay = 500;

let nextStepT;
let iter;

function setup() {
  createCanvas(400, 400);
  
  nextStepT = millis();
  iter = drawSequence();
}

function draw() {
  if (nextStepT < millis()) {
    let n = iter.next();
    if (n.value) {
      // done, reset
      iter = drawSequence();
    }
    
    nextStepT = millis() + delay;
  }
}

function* drawSequence() {
  background(220);
  for (let i = 0; i < 10; i++) {
    yield false;
    circle(random(0, width), random(0, height), 20);
  }
  yield true;
}

```

For your use case this could be needlessly complex, but I have found uses for it.

### 4. Re-structure your code so that you “delay” elements getting drawn by controlling what gets drawn based on time

This would be preferable if 1) you don’t want to dive into advanced JavaScript concepts like Promises or iterators, or 2) you have a mix of things being rendered in real time and on a timeline. For example:

```auto
const delay = 500;
const spacing = 40;

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  let done = false;
  let columns = floor(width / 40) - 1;
  let rows = floor(height / 40) - 1;
  for (let y = 0; !done && y < rows; y++) {
    for (let x = 0; x < columns; x++) {
      // limit how many circles are displayed based on time
      if ((y * columns + x) * delay > millis()) {
        done = true;
        break;
      }
      
      circle((x + 1) * spacing, (y + 1) * spacing, 20);
    }
  }
  
  // also draw something in real time
  circle(mouseX, mouseY, 20);
}

```
