正确清除多个超时

时间:2015-04-29 10:31:13

标签: javascript settimeout multiple-instances scoping cleartimeout

我在过去的一天里一直在努力解决这个问题。

我试图获得一些时髦的文字效果,基本上是一个美化的字符串创作。 它写了一条有点像广告牌的线,为了做到这一点,我使用了setTimeout。 事情是我想把它放在一个函数中,所以我可以重用它并在不同的元素上多次调用它。

问题是我需要将文本更新到新文本的中途。 为此,我清除了超时,但除非定时器变量超出范围,否则它不会清除。

由于实用性,我无法在功能之外使用它; 我不确定它会被调用多少次,在函数外面声明20个时间变量只是感觉不对。

这里的代码在一个项目上运行正确 (单击多次以中断并重新启动)



    var t;
    function writeStats(str,dest) {

        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        function randomChar(type){
            var pool = "";

            if (type == "lowerLetter"){
                pool = "abcdefghijklmnopqrstuvwxyz0123456789";
            }
            else if (type == "upperLetter"){
                pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            }
            else if (type == "symbol"){
                pool = ",.?/\\(^)![]{}*&^%$#'\"";
            }

            var arr = pool.split('');
            return arr[Math.floor(Math.random()*arr.length)];
        }

        str = str.split('');

        var types = [],
            letters = [];

        for(var i=0;i<str.length;i++){

            var ch = str[i];

            if(ch == " "){
                types[i] = "space";
                continue;
            }
            else if(/[a-z]/.test(ch)){
                types[i] = "lowerLetter";
            }
            else if(/[A-Z]/.test(ch)){
                types[i] = "upperLetter";
            }
            else {
                types[i] = "symbol";
            }

            letters.push(i);
        }

        clearTimeout(t);

        (function shuffle(start){

            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i,
                len = letters.length,
                strCopy = str.slice(0); // Fresh copy of the string

            if(start>len){
                return;
            }

            // All the work gets done here
            for(i=Math.max(start,0); i < len; i++){

                // The start argument and options.step limit
                // the characters we will be working on at once

                if( i < start+options.step){
                    // Generate a random character at this position
                    strCopy[letters[i]] = randomChar(types[letters[i]]);
                }
                else {
                    strCopy[letters[i]] = "";
                }
            }

            //el.text(strCopy.join(""));
            el = strCopy.join("");
            //console.log(el);
            $('.'+dest).text(el);

            t = setTimeout(function(){

                shuffle(start+1);

            },500/options.fps);

        })(-options.step);

    }

    $(document).ready(function(){
        $(document).click(function(){
            writeStats('this sentence is a great one','t1');
        });
    });
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="t1"></div>
<div class="t2"></div>
&#13;
&#13;
&#13; 和小提琴脚本:https://jsfiddle.net/phjzfw15/

如果我把t变量放在函数中,就像它一样,它不像以前一样工作:

&#13;
&#13;
function writeStats(str,dest) {
        var t;
        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        function randomChar(type){
            var pool = "";

            if (type == "lowerLetter"){
                pool = "abcdefghijklmnopqrstuvwxyz0123456789";
            }
            else if (type == "upperLetter"){
                pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            }
            else if (type == "symbol"){
                pool = ",.?/\\(^)![]{}*&^%$#'\"";
            }

            var arr = pool.split('');
            return arr[Math.floor(Math.random()*arr.length)];
        }

        str = str.split('');

        var types = [],
            letters = [];

        for(var i=0;i<str.length;i++){

            var ch = str[i];

            if(ch == " "){
                types[i] = "space";
                continue;
            }
            else if(/[a-z]/.test(ch)){
                types[i] = "lowerLetter";
            }
            else if(/[A-Z]/.test(ch)){
                types[i] = "upperLetter";
            }
            else {
                types[i] = "symbol";
            }

            letters.push(i);
        }

        clearTimeout(t);

        (function shuffle(start){

            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i,
                len = letters.length,
                strCopy = str.slice(0); // Fresh copy of the string

            if(start>len){
                return;
            }

            // All the work gets done here
            for(i=Math.max(start,0); i < len; i++){

                // The start argument and options.step limit
                // the characters we will be working on at once

                if( i < start+options.step){
                    // Generate a random character at this position
                    strCopy[letters[i]] = randomChar(types[letters[i]]);
                }
                else {
                    strCopy[letters[i]] = "";
                }
            }

            //el.text(strCopy.join(""));
            el = strCopy.join("");
            //console.log(el);
            $('.'+dest).text(el);

            t = setTimeout(function(){

                shuffle(start+1);

            },500/options.fps);

        })(-options.step);

    }

    $(document).ready(function(){
        $(document).click(function(){
            writeStats('this sentence is a great one','t1');
        });
    });
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="t1"></div>
    <div class="t2"></div>
&#13;
&#13;
&#13; ...如果您愿意,可以选择相对小提琴:https://jsfiddle.net/phjzfw15/1/

如果您运行该代码段,您将会看到它不再正常工作。 反复单击将显示旧句子仍然存在并被覆盖。 如何在函数内正确清除超时?

我认为&#34; t&#34;变量是每个函数的本地变量,并且会创建一个单独的实例吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

好的,这是一个愚蠢的版本(也许之前的代码量太多了) 正确版本

    var starr = [
        'bloop the boop',
        'cammy the shadow',
        'i like cauliflower',
        'bro, i kick u hard',
        'like measels? I dont.',
        'eat fish and pie'
    ];

    var timer;

    function writeStats(str, dest) {
        
        $('.'+dest).text('');

        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        str = str.split('');
        
        clearTimeout(timer);
        var ll = '';
        (function shuffle(start){
            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i, len = str.length, el;
            

            if(start>=len){
                return;
            }          
            ll = ll + str[start];
            $('.'+dest).text(ll);

            timer = setTimeout(function(){

                shuffle(start+1);

            },1500/options.fps);
        })(0);

    }

    $(document).ready(function(){
        var index = 0;
        $(document).click(function(){
            writeStats(starr[index],'t1');
            if (index == 5) index = 0; else index++;
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
Correct version
<div class="t1">Click anywhere multiple times</div>

不工作版

    var starr = [
        'bloop the boop',
        'cammy the shadow',
        'i like cauliflower',
        'bro, i kick u hard',
        'like measels? I dont.',
        'eat fish and pie'
    ];



    function writeStats(str, dest) {
        var timer;
        $('.'+dest).text('');

        var options = {
                "step"  : 8,    // How many times should the letters be changed
                "fps"   : 25,   // Frames Per Second
                "text"  : ""    // Use this text instead of the contents
            }
        
        str = str.split('');
        
        clearTimeout(timer);
        var ll = '';
        (function shuffle(start){
            // This code is run options.fps times per second
            // and updates the contents of the page element

            var i, len = str.length, el;
            

            if(start>=len){
                return;
            }          
            ll = ll + str[start];
            $('.'+dest).text(ll);

            timer = setTimeout(function(){

                shuffle(start+1);

            },1500/options.fps);
        })(0);

    }

    $(document).ready(function(){
        var index = 0;
        $(document).click(function(){
            writeStats(starr[index],'t1');
            if (index == 5) index = 0; else index++;
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
NOT WORKING VERSION (please note I just moved the timer declaration inside the function)
<div class="t1">Click anywhere multiple times fast</div>

答案 1 :(得分:0)

最后让它发挥作用。 对于后代...

    var starr = [
        'bloop the boop',
        'cammy the shadow',
        'i like cauliflower',
        'bro, i kick u hard',
        'like measels? I dont.',
        'eat fish and pie'
    ];

        var writer = function(){
            
            var timer;

            this.writeStat = function(str,dest) {

                var options = { "step"  : 8, "fps"   : 25, "text"  : "" }
                
                str = str.split('');
                
                clearTimeout(timer);
                var ll = '';
                
                (function shuffle(start){
                    // This code is run options.fps times per second
                    // and updates the contents of the page element
        
                    var i, len = str.length, el;
                    
        
                    if(start>=len){
                        return;
                    }          
                    ll = ll + str[start];
                    $('.'+dest).text(ll);
        
                    timer = setTimeout(function(){
        
                        shuffle(start+1);
        
                    },1500/options.fps);
                })(0);
            }
        }

    $(document).ready(function(){
        var index = 0;
        w = new writer;
        y = new writer;
        $(document).click(function(){
            
            w.writeStat(starr[index],'t1');
            y.writeStat(starr[index],'t2');
            if (index == 5) index = 0; else index++;
        });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="t1"></div>
<div class="t2"></div>