I'm trying to print to a div one character at a time. It works, however, it runs both lines at the same time so that all I get is a jumbled mess.
How can I make the commands run one after the other?
function print(str){
var arr = str.split("");
var i = 0;
function write(){
setTimeout(function(){
if(i < arr.length){
var cont = $(".content").html();
cont = cont.replace("_","");
$(".content").html(cont + arr[i] + "_");
i++;
write();
}
},30);
}
write();
}
var str = [
"I am the egg man",
"I am the walrus"
];
for(x in str){
print(str[x];
}
jsFiddle: http://jsfiddle.net/PscNC/1/
bobef is right.
Add another argument to print, which is a callback. And you should call the print method inside another recursive method instead a loop.
This is based on jfriend's answer, but it uses primitives with promises rather than promises at a high level. I believe this makes for cleaner code.
First, let's write a function that represents a delay with promises:
Next, let's use promises to their fullest
Here is a fiddle illustrating this solution: http://jsfiddle.net/feq89/
Just for fun, here is an ES6 solution without jQuery:
You have two asynchronous functions that you start one right after the other so they run in parallel. If you want them to run serially, then you have to create some sort of notification when the first one is done so you then can trigger the start of the next one and so on. This can be done a number of ways (I show three ways below). You can use a callback, you can use promises and you can avoid having to sequence the async operations at all.
Method #1 - Completion Callback
Here's adding a callback to your print function and then use that to trigger the next string to go and then changing your iteration of strings to use the callback:
Working demo: http://jsfiddle.net/jfriend00/Lyu5V/
FYI, there's really no reason to split your string into an array. You can access the individual characters of the string with the
.charAt(index)
method.Method #2 - Promises - use .then() to sequence operations
And, here's a version of your code using promises instead of passing the callback:
Working demo: http://jsfiddle.net/jfriend00/97UtX/
Method #3 - Avoid sequencing by combining data into one single operation
And, if you want to simplify/DRY it up a bit, you can do this which avoids having to sequence the successive operations by just turning it into one longer operation and I made a few simplifications to your code:
Working demo: http://jsfiddle.net/jfriend00/TL8pP/