按顺序执行JavaScript

按顺序执行JavaScript,javascript,Javascript,我试图一次打印一个字符到div。但是,它可以工作,同时运行两行,所以我得到的只是一团混乱 如何使命令一个接一个地运行 function print(str){ var arr = str.split(""); var i = 0; function write(){ setTimeout(function(){ if(i < arr.length){ var cont = $(".content

我试图一次打印一个字符到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];
}
函数打印(str){
var arr=str.split(“”);
var i=0;
函数写入(){
setTimeout(函数(){
如果(i

jsFIDLE:

您有两个异步函数,您可以一个接一个地启动它们,以便它们并行运行。如果您希望它们串行运行,那么您必须在第一个异步函数启动后创建某种通知,以便触发下一个异步函数的启动,依此类推。这可以通过多种方式完成(我在下面展示了三种方法)。您可以使用回调,可以使用承诺,并且可以避免对异步操作进行排序

方法#1-完成回调 下面将向打印函数添加回调,然后使用该回调触发下一个字符串,然后更改字符串的迭代以使用回调:

工作演示:


方法#3-通过将数据合并到单个操作中来避免排序 而且,如果您想简化/简化它,您可以这样做,通过将其转换为一个较长的操作来避免连续操作的顺序,我对您的代码进行了一些简化:

工作演示:

$(函数(){
功能打印(str){
变量i=0,项目=$(“.content”);
函数写入(){
setTimeout(函数(){
如果(i
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();
函数打印(str,\u cb){
var arr=str.split(“”);
var i=0;
函数写入(){
setTimeout(函数(){
如果(i
这是基于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(){})` 
下面是一把小提琴,演示了这个解决方案:

为了好玩,这里有一个没有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, "")));

类似地,您有两个异步函数,并且您同时启动它们。如果您希望在启动第二个函数之前完成第一个函数,那么您需要第一个函数发出通知,这样您就可以启动第二个函数。顺便说一句,因为Javascript中的in循环不打算用作for each循环和标准不保证密钥的迭代顺序。请使用
进行(var i=0;ii如果你想一个接一个地写句子,而不是用新句子替换最后一个句子,那么你所要做的就是将
p中的参数传递给
初始值,然后启动
数据
。在我记忆中,没有检查-不,没有,并且有关于将其正式记录到API中的讨论,它从永远都在那里:)是的,这也是我的理解。顺便说一句-可以通过在数组中构建字符串并使用
.join(“”)输出来避免终端“u”)
。也减少了GC的工作。@Roamer-1888我以为终端
\uuuu
插入符号应该在那里(就像你在文字处理器中键入时)。可以
。然后
减少调用并手动删除它。至少在
v8
中,这段代码相当慢(由于
.reduce
、字符串属性访问等原因)无论如何,我假设您同时执行此操作的次数不超过1000次。我不确定您对
.join
的建议是否有效,介意做点小动作吗?
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(){})` 
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, "")));