Multiply the number of miliseconds so the setTimeout that comes after has the correct time assigned. Also, you was multiplying the taskTime
and i
, which was always 0. I replaced i
with i + 1
instead.
Just try this JavaScript code instead (it works):
function notify(msg, loops, taskTime) {
var ul = document.getElementById("notifications");
for (let i = 0; i < loops; i++) {
(function (i) {
window.setTimeout(function () {
var li = document.createElement("li")
li.appendChild(document.createTextNode(`${msg}`));
ul.appendChild(li)
}, taskTime * (i + 1))
}(i))
}
}
notify('Hello', 1, 5000)
notify('Morning', 4, 5000 * 2)
notify('Evening', 1, 6000 + 5000 * 6)
Based on Mike’s comment:
tasks = [
{message: 'Hello', delay: 5000},
{message: 'Morning', delay: 5000},
{message: 'Morning', delay: 5000},
{message: 'Morning', delay: 5000},
{message: 'Morning', delay: 5000},
{message: 'Evening', delay: 6000},
]
function runTask(index) {
var ul = document.getElementById("notifications");
var li = document.createElement("li");
li.appendChild(document.createTextNode(`${tasks[index].message}`));
ul.appendChild(li);
if(index < tasks.length - 1){
setTimeout( () => runTask(index + 1), tasks[index].delay);
}
}
if(tasks.length > 0) runTask(0); //make sure the task list has at least one element.
In modern JavaScript, async
functions should probably be your first port of call when writing async code. They are clearer and usually easier to understand.
In the following, delay
promisifies setTimeout
.
notify
adds li
elements to the document in a loop, with a delay added at the beginning of each iteration.
I am unsure if this behaves as you need for the first "Hello"
.
const delay = (ms) => new Promise((res) => setTimeout(res, ms))
const ul = document.getElementById("notifications")
async function notify(msg, count, ms) {
for (let i = 0; i < count; i++) {
await delay(ms)
const li = document.createElement('li')
li.innerText = `${msg} ${Date()}`
ul.appendChild(li)
}
}
(async () => {
await notify('Hello', 1, 5000)
await notify('Morning', 4, 5000)
await notify('Evening', 1, 6000)
})()
<p>Notifications will appear below:</p>
<ul id="notifications"></ul>
I’m trying to make a program that adds text to a web-page, like so:
Hello
Morning
Morning
Morning
Morning
Evening
There should be:
- 5 second delay between “Hello” and the first “Morning”.
- 5 second delay between each “Morning”.
- 6 second delay between the last “Morning” and “Evening”.
Here’s the whole HTML and JavaScript I’ve got so far.
function notify(msg, loops, taskTime) {
var ul = document.getElementById("notifications");
for (let i = 0; i < loops; i++) {
(function(i) {
window.setTimeout(function() {
var li = document.createElement("li")
li.appendChild(document.createTextNode(`${msg}`));
ul.appendChild(li)
}, taskTime * i)
}(i))
}
}
notify('Hello', 1, 5000)
notify('Morning', 4, 5000)
notify('Evening', 1, 6000)
<div>
<ul id="notifications" style="list-style-type:none;margin-left:10%;"></ul>
</div>
My problem is that on loading the web-page, the output is:
Hello
Morning
Evening
Morning
Morning
Morning
How can I make sure that the function is ran in the order I want it to and not this mixed output? The first 3 outputs also appear instantly instead of a delay. How do I avoid that?
You should add an explanation for your code. Code dumps are rarely useful.