First, we need to fix mistakes in the uploadSteps
function:
function uploadSteps(maxStep) {
// here change `var x` to `let x` to avoid problems
// like here - https://stackoverflow.com/q/750486/5811984
for (let x = 1; x <= maxStep; x++){
setTimeout(function() {
// notice how here ajaxFetch(x) is wrapped into a function,
// otherwise it gets called right away
ajaxFetch(x)
}, 20);
}
}
Now here's another problem - all the setTimeout will be called with 20ms
delay, that means that all of them will be executed at the same time, but ~20ms after uploadSteps()
was called.
Let's see what happens when maxStep=3
(assuming your CPU is very fast because that is irrelevant for understanding the problem):
Time passed | what happens
--------------------------
0ms | setTimeout(ajaxFetch(1), 20) is called
0ms | setTimeout(ajaxFetch(2), 20) is called
0ms | setTimeout(ajaxFetch(3), 20) is called
20ms | ajaxFetch(1) is called
20ms | ajaxFetch(2) is called
20ms | ajaxFetch(3) is called
So as you see all ajaxFetch
's are called at the same time, and I am assuming that's not exactly what you need. What you might be looking for is this:
Time passed | what happens
--------------------------
0ms | setTimeout(ajaxFetch(1), 20) is called
0ms | setTimeout(ajaxFetch(2), 40) is called
0ms | setTimeout(ajaxFetch(3), 60) is called
20ms | ajaxFetch(1) is called
40ms | ajaxFetch(2) is called
60ms | ajaxFetch(3) is called
Which can be implemented with a slight change to your code
function uploadSteps(maxStep) {
for (let x = 1; x <= maxStep; x++){
setTimeout(function() {
ajaxFetch(x)
}, 20 * x); // change delay from 20 -> 20 * x
}
}
Also it looks like you don't need to return anything from ajaxFetch()
, so it's better to make it async so it does not block the code execution:
function ajaxFetch(s) {
$.ajax({
type: "POST",
url: "post.php",
data: {
step: s
},
// async: false, -- remove this, it's true by default
dataType: 'JSON',
success: function (response) {
$("#loadText").text(response.stepText);
console.log(response.stepText);
}
});
}
Even if you actually do need to return something for fetchAjax()
, it's better to keep it async and use callbacks/promises. jQuery actually strongly discourages using async: false
in any case.
If the reason you added setTimeout
s is to make sure all the steps are executed in order, then it's not the right way to do that. The problems are:
- Let's say it took 100ms for the server to respond to the first request, and 10ms for the second one. Even with the 20ms delay the second request will be executed first. And just increasing the delay is not the solution, because:
- If your server responds much faster the delay, you are introducing an unnecessary wait for the user.
It's better to add a callback from ajaxFetch()
that will be called when ajax fetching is done, and then you'd call the next ajaxFetch()
after you receive the callback.