簡體   English   中英

按順序執行JavaScript

[英]Executing JavaScript in Order

我正在嘗試一次向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/

您有兩個異步函數,它們一個接一個地啟動,因此它們可以並行運行。 如果希望它們連續運行,則必須在第一個通知完成時創建某種通知,以便隨后觸發下一個通知的開始,依此類推。 這可以通過多種方式完成(我在下面顯示了三種方式)。 您可以使用回調,可以使用Promise,並且可以完全避免對異步操作進行排序。

方法1-完成回調

這里向打印函數添加了一個回調,然后使用該回調來觸發下一個字符串,然后更改字符串的迭代以使用該回調:

工作演示: 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)方法訪問字符串的各個字符。


方法2-承諾-使用.then()對操作進行排序

而且,這是使用promise而不是傳遞回調的代碼版本:

工作演示: 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());

});

方法3-通過將數據合並到一個操作中避免排序

而且,如果您想對其進行一些簡化/干燥,可以這樣做,從而避免了將連續的操作變成一個更長的操作而不得不對連續的操作進行排序的過程,並且我對代碼進行了一些簡化:

工作演示: 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(""));

});

這是基於jfriend的答案的,但是它使用帶有promise的原語,而不是高級的promise。 我相信這可以使代碼更簡潔。

首先,讓我們編寫一個表示承諾的延遲的函數:

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, "")));

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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM