我正在尝试一次打印一个div。然而,它有效,它同时运行两条线,所以我得到的只是乱七八糟的混乱。
如何让命令一个接一个地运行?
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/
答案 0 :(得分:1)
你有两个异步函数,你可以一个接一个地启动它们,所以它们并行运行。如果您希望它们以串行方式运行,那么您必须在完成第一个通知时创建某种通知,这样您就可以触发下一个通知的开始,依此类推。这可以通过多种方式完成(我在下面展示了三种方式)。你可以使用回调,你可以使用promises,你可以避免必须对异步操作进行排序。
这里为你的print函数添加一个回调,然后使用它来触发下一个字符串,然后改变你的字符串迭代来使用回调:
工作演示:http://jsfiddle.net/jfriend00/Lyu5V/
$(function() {
function print(str, fn) {
var i = 0;
var items = $(".content");
function write() {
setTimeout(function() {
if (i < str.length) {
items.html(items.html().replace("_", "") + str.charAt(i) + "_");
i++;
write();
} else {
fn();
}
}, 100);
}
write();
}
var data = [
"I am the egg man...",
"I am the walrus"
];
var i = 0;
function next() {
if (i < data.length) {
print(data[i++], next);
}
}
next();
});
仅供参考,我们没有理由将你的字符串拆分成数组。您可以使用.charAt(index)
方法访问字符串的各个字符。
而且,这是使用promises而不是传递回调的代码版本:
工作演示:http://jsfiddle.net/jfriend00/97UtX/
$(function() {
function print(str) {
var i = 0, items = $(".content"), def = $.Deferred();
function write() {
setTimeout(function() {
if (i < str.length) {
items.html(items.html().replace("_", "") + str.charAt(i) + "_");
i++;
write();
} else {
def.resolve();
}
}, 100);
}
write();
return def.promise();
}
var data = [
"I am the egg man..",
"I am the walrus"
];
data.reduce(function(p, item) {
return p.then(function() {
return print(item);
});
}, $.Deferred().resolve());
});
而且,如果你想简化/干掉它,你可以做到这一点,避免必须通过将其转换为一个更长的操作来对连续操作进行排序,并对代码进行了一些简化:
工作演示:http://jsfiddle.net/jfriend00/TL8pP/
$(function() {
function print(str) {
var i = 0, items = $(".content");
function write() {
setTimeout(function() {
if (i < str.length) {
items.html(items.html().replace("_", "") + str.charAt(i) + "_");
i++;
write();
}
}, 100);
}
write();
}
var data = [
"I am the egg man..",
"I am the walrus"
];
print(data.join(""));
});
答案 1 :(得分:1)
这是基于jfriend的答案,但它使用的是带有承诺的原语而不是高级承诺。我相信这可以使代码更清晰。
首先,让我们编写一个代表延迟的函数:
function delay(ms){ // generic delay function
var d = $.Deferred();
setTimeout(d.resolve, ms);
return d;
}
接下来,让我们充分利用承诺
var delay100 = delay.bind(null, 100); // a 100 ms delay
function write(el, str, initial) { // write a single word
return [].reduce.call(str, function (prev, cur) { // reduce is generic
return prev.then(delay100).then(function (letter) {
initial += cur;
el.text(initial + "_");
});
}, $.when());
}
data.reduce(function (p, item) {
return p.then(function () { // when the last action is done, write the next
return write($(".content"), item, ""); // might want to cache this
});
}, $.ready.promise()); // we don't need `$(function(){})`
这是一个说明这个解决方案的小提琴:http://jsfiddle.net/feq89/
只是为了好玩,这是一个没有jQuery的ES6解决方案:
var delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
var write = (el, str, initial) =>
[].reduce.call(str, (prev, cur) =>
prev.then(() => delay(100)).then(() => {
initial += cur;
el.textContent = initial + "_";
});
}, Promise.resolve());
var content = document.querySelector(".content");
data.reduce((p, item) => p.then(() => write(content, item, "")));
答案 2 :(得分:0)
bobef是对的。
添加另一个参数print,这是一个回调。 你应该在另一个递归方法中调用print方法而不是循环。
function print(str, _cb){
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();
} else {
_cb();
}
},30);
}
write();
}
var str = [
"I am the egg man",
"I am the walrus"
];
var j = 0,
callback = function () {
if(j < str.length){
print (str[j++], callback);
}
};
callback();