JavaScript setInterval()
We continue in the Speedy Chef project folder throughout this section.
Repeating orders
The orders are working and generating randomly as soon as the game starts. But we also want them to keep generating throughout the game.
To do this, JavaScript provides us with a method called setInterval
.
Using setInterval
The setInterval
method will run a function after a certain time delay. It is available on the window
object, meaning we call it on its own:
generateNewOrder();
// call setInterval at the bottom of index.js:
setInterval();
Then we pass in two things. First is a function we want to run. We can type in a function directly, or reference an existing function name, which we already have:
// move generateNewOrder into setInterval:
setInterval(generateNewOrder);
Separated by a comma, we pass in a time delay in milliseconds between each time we call this function, so 1000 milliseconds will be 1 second.
setInterval(generateNewOrder, 3000);
To check this works, inside of generateNewOrder
, we can log the orders array and check a new one is being added every three seconds:
function generateNewOrder() {
// ...
// add at bottom of function
console.log(orders);
}
The console should show a new array added every three seconds.
Adding new orders to the DOM
Earlier we created a function called createOrdersList
. This function took the orders array and added them all to the DOM.
We now call this function each time we generate a new order:
function generateNewOrder() {
// ...
// Call createOrdersList() in place of the previous log:
// console.log(orders);
createOrdersList();
}
Issues to resolve
There are two things here we need to fix:
- The orders are displaying before we press the start button.
- We need to only add the new additional orders, not duplicate everything we have.
Issue 2 can be resolved by going to the createOrdersList
function, and clearing the orders before adding new ones:
function createOrdersList() {
// clear orders at the beginning of the function:
document.querySelector('#orders').innerHTML = '';
// ...
}
For issue 1, wrap the setInterval
into a new function. This means we can call it only when the game has started:
function ordersTimer() {
// create ordersTimer function and move inside setInterval:
setInterval(generateNewOrder, 3000);
}
And call this function from the startOfGame
function:
function startOfGame() {
// add to end of function:
ordersTimer();
}
Restricting the game time
The setInterval
method is also useful to create a countdown timer for the game so it only runs for a set amount of time.
For this we can create some variables. Add the following alongside our existing variables:
// 1. the time we want the game to run for in seconds:
const gameLength = 300;
// 2. then a second variable, set to the gameLength:
let countdownTime = gameLength;
// we do this so we can deduct this each second, and keep the original value
// 3. Then set this to display in the game:
document.querySelector(
'#gameLength'
).innerText = `Game length is ${gameLength} seconds`;
We now need to do two things:
- Create a function to reduce the countdownTime variable by one second.
- Then call this function once a second using setInterval.
First, create the function at the bottom of script:
function countdownTimer() {
// reduce variable value
countdownTime -= 1;
// update the DOM
document.querySelector(
'#gameLength'
).innerText = `Time left: ${countdownTime}`;
}
Inside the startOfGame
function, we can call this function each second:
function startOfGame() {
// ...
setInterval(countdownTimer, 1000);
}
Try this out in the browser by starting the game and watch the time count down!
Completed code after this lesson
If needed, here is the completed code we added to the starter file (index.js
):
let oven = [];
const ovenCapacity = 6;
let pizzasCompleteForOrder = 0;
let gameStarted = false;
const gameLength = 300;
let countdownTime = gameLength;
document.querySelector(
"#gameLength"
).innerText = `Game length is ${gameLength} seconds`;
document.querySelector("#endBtn").style.display = "none";
function buildElement(elementName, elementContent) {
const element = document.createElement(elementName);
const content = document.createTextNode(elementContent);
element.appendChild(content);
return element;
}
function createListOfPizzas(pizzas) {
const pizzaList = document.createElement("ul");
pizzas.forEach(function (pizza) {
const orderQuantityEl = buildElement("span", `${pizza.quantity} - `);
const pizzaNameElement = buildElement("span", pizza.name);
pizzaNameElement.classList.add("pizza_name");
const pizzaItem = document.createElement("li");
pizzaItem.append(orderQuantityEl, pizzaNameElement);
pizzaList.appendChild(pizzaItem);
});
return pizzaList;
}
function createSingleOrder(order) {
const orderWrapper = document.createElement("div");
orderWrapper.className = "order_wrapper";
orderWrapper.addEventListener("click", selectCurrentOrder);
const orderNumberEl = buildElement("h4", `Order: ${order.id}`);
orderWrapper.appendChild(orderNumberEl);
const pizzaList = createListOfPizzas(order.pizzas);
orderWrapper.appendChild(pizzaList);
return orderWrapper;
}
function createOrdersList() {
document.querySelector("#orders").innerHTML = "";
orders.forEach(function (order) {
const singleOrder = createSingleOrder(order);
document.querySelector("#orders").appendChild(singleOrder);
});
}
function selectCurrentOrder(e) {
const pizzas = document.querySelectorAll(".pizza_name");
pizzas.forEach(function (pizza) {
pizza.addEventListener("click", setCurrentPizza);
});
if (document.querySelector("#working_on").children.length > 1) {
return;
}
let element = e.target;
const orderWrapper = element.closest(".order_wrapper");
if (orderWrapper !== null) {
orderWrapper.removeEventListener("click", selectCurrentOrder);
const orderDiv = document.querySelector("#working_on");
orderDiv.appendChild(orderWrapper);
}
}
function setCurrentPizza(e) {
const pizzaName = e.target.innerText;
document.querySelector("#current_pizza").innerText = pizzaName;
displayMethod(pizzaName);
}
function displayMethod(pizzaName) {
document.querySelector("#pizza_name").innerText = pizzaName;
const selectedPizza = pizzas.find((pizza) => pizza.name === pizzaName);
const methodSteps = selectedPizza.method.split(".");
document.querySelector("#pizza_method").innerHTML = "";
methodSteps.forEach(function (method) {
const element = buildElement("li", method);
document.querySelector("#pizza_method").appendChild(element);
});
}
function addToOven() {
pizzasCompleteForOrder++;
const pizzaName = document.querySelector("#current_pizza").innerText;
if (pizzaName) {
const pizzaForOven = {
name: pizzaName,
timeAdded: "5/5/28",
};
oven.push(pizzaForOven);
displayOvenItems();
}
}
document.querySelector("#addToOven").addEventListener("click", addToOven);
function displayOvenItems() {
document.querySelector("#oven").innerHTML = "";
oven.forEach(function (pizza) {
const pizzaDiv = document.createElement("div");
pizzaDiv.className = "pizza_div";
const image = document.createElement("img");
image.src = "pizza.svg";
const pizzaName = buildElement("p", `(${pizza.name})`);
pizzaDiv.append(image, pizzaName);
document.querySelector("#oven").appendChild(pizzaDiv);
});
}
function startOfGame() {
if (gameStarted) {
return;
}
document.querySelector("#startBtn").style.display = "none";
document.querySelector("#endBtn").style.display = "inline";
gameStarted = true;
const orders = document.getElementsByClassName("order_wrapper");
Array.from(orders).forEach(function (order) {
order.remove();
});
createOrdersList();
ordersTimer();
setInterval(countdownTimer, 1000);
}
function endOfGame() {
gameStarted = false;
document.querySelector("#endBtn").style.display = "none";
document.querySelector("#startBtn").style.display = "inline";
}
document.querySelector("#startBtn").addEventListener("click", startOfGame);
document.querySelector("#endBtn").addEventListener("click", endOfGame);
let orderNumber = orders.length + 1;
function generateNewOrder() {
let pizzas = [];
const orderItem = Math.ceil(Math.random() * 5);
for (i = 1; i <= orderItem; i++) {
pizzas.push(generateNewPizza());
}
const newOrder = {
id: orderNumber,
pizzas,
};
orders.push(newOrder);
orderNumber++;
createOrdersList();
}
function generateNewPizza() {
const quantity = Math.ceil(Math.random() * 3);
const randomPizza = pizzas[Math.floor(Math.random() * pizzas.length)];
const pizza = {
quantity,
name: randomPizza.name,
};
return pizza;
}
generateNewPizza();
function ordersTimer() {
setInterval(generateNewOrder, 3000);
}
function countdownTimer() {
countdownTime -= 1;
document.querySelector(
"#gameLength"
).innerText = `Time left: ${countdownTime}`;
}