我不能同时运行setInterval和另一个函数

时间:2016-08-21 02:24:36

标签: javascript html json timer

当我点击按钮时,我有两个应该运行的功能。第一个函数是一个setInterval函数,它将变量 num 递增0.01并将其显示在名为 result 的div id中。第二个函数将对象文字生成为json字符串,并将其显示在名为 output 的div id中。当我单击按钮时,只输出JSON字符串,但似乎setInterval没有运行,我不知道为什么。以下是link例如

HTML

<button>
click
</button>
<div id="result">

</div>
<div id="output">

</div>

的Javascript

var timer,
        result = document.getElementById("result"),
    num,
    link ={
     name:"link",
     weapon:"master sword",
     mute:true,
     race:"hyrulian",
     age:16
    };

/* ---------- GENERATE JSON OBJECT --*/
function generate(){
var data = {};
 for(var prop in link){
    data[prop] = link[prop];
 }
 data = JSON.stringify(data);
 document.getElementById("output").innerHTML = data;
}

/* ---------- CLICK BUTTON --*/
document.querySelector("button").onclick = function(){

num = 0;
  function callBack(){
     num += 0.01;
   result.innerHTML = num.toFixed(2);

  }
  timer = setInterval(callBack,10);
  generate();
  clearInterval(timer);

}

3 个答案:

答案 0 :(得分:1)

更新了我的答案:你必须包装你的callBack();使用匿名函数在setInterval中运行。这是因为setInterval期望对应该每隔几毫秒(您指定的间隔)执行的Function的引用。您应该像setInterval( function(){ callBack(); }, 10);一样使用它。这应该会给你想要的结果。

相同的代码,我刚刚更新了setInterval( function(){ callBack(); }, 10);行:

var timer,
    result = document.getElementById("result"),
num,
link ={
 name:"link",
 weapon:"master sword",
 mute:true,
 race:"hyrulian",
 age:16
};

/* ---------- GENERATE JSON OBJECT --*/
function generate(){
var data = {};
for(var prop in link){
   data[prop] = link[prop];
}
data = JSON.stringify(data);
document.getElementById("output").innerHTML = data;
}

/* ---------- CLICK BUTTON --*/
document.querySelector("button").onclick = function(){

num = 0;
  function callBack(){
 num += 0.01;
 result.innerHTML = num.toFixed(2);

 }
 timer = setInterval( function(){ callBack(); },10); // I modified this line
 // timer = setInterval(callBack,10);
 generate();
 clearInterval(timer);
 // setTimeout( function(){ clearInterval(timer); }, 1000); // This can be used to test that the timer has indeed started, you can wait 1 second before you clear the timer

 }

答案 1 :(得分:0)

这是因为您setInterval(callBack,10);,但是您使用clearInterval(timer);清除了间隔。

删除clearInterval(timer);,您就可以让计时器正常工作。

答案 2 :(得分:0)

JavaScript是单线程的。为了使您设置的callBack函数在运行setInterval(callBack,10)的10毫秒间隔内运行,您的JavaScript代码必须停止运行(即完成)。在您的代码放弃处理器之前,不会执行任何类型的回调函数。

因此,在您的代码中:

timer = setInterval(callBack,10);  //Set up the interval timer
generate();  //generate(): Even if this takes 10 minutes to complete
             //  the callBack function will not be executed from the interval timer.
clearInterval(timer); //Clear the interval timer. While the interval may have expired
                      //  (depending on how long the generate() function took), the 
                      //  the callBack function will have never run because the processor
                      //  has been busy continuing to run the code that came after calling 
                      //  setInterval.  Clearing the interval timer here results in 
                      //  callBack never being executed.

因此,如果您希望callBack执行一次,则需要在您当时执行的代码完成之前调用clearInterval(timer)

如果您希望callBack只执行一次,那么您可以使用setTimeout()

计划需要多长时间:

如果您正在尝试计算某事需要多长时间:

  1. 获取您想要的时间之前的当前时间
  2. 做你想要的时间
  3. 完成后抽出时间(再次使用window.performance.now())。
  4. 计算并显示两次之间的差异。
  5. 所以,修改你的代码:

    var timer,
        result = document.getElementById("result"),
        link = {
            name: "link",
            weapon: "master sword",
            mute: true,
            race: "hyrulian",
            age: 16
        };
    
    /* ---------- GENERATE JSON OBJECT --*/
    function generate() {
        var data = {};
        for (var prop in link) {
          data[prop] = link[prop];
        }
        data = JSON.stringify(data);
        document.getElementById("output").innerHTML = data;
    }
    
    /* ---------- CLICK BUTTON --*/
    document.querySelector("button").onclick = function() {
        function showResult(time, precision, units) {
            result.innerHTML = time.toFixed(precision) + ' ' + units;
        }
    
        var startTime = window.performance.now();
        generate();
        var endTime = window.performance.now();
      
        //These times are floating point numbers in milliseconds
        var elapsedMs = endTime - startTime;
        showResult(elapsedMs,3,'milliseconds');
    
        //If you want to show the time in microseconds:
        //var elapsedUs = elapsedMs * 1000;
        //showResult(elapsedUs,0,'microseconds');
    }
    <button>
      click
    </button>
    <div id="result">
    </div>
    
    <div id="output">
    </div>

    但是,如果您的真正目标是确定运行generate()所需的平均时间,那么您需要时间来运行生成大量的时间,而不仅仅是一次。

    var result = document.getElementById("result");
    var link = {
            name: "link",
            weapon: "master sword",
            mute: true,
            race: "hyrulian",
            age: 16
        };
    
    /* ---------- GENERATE JSON OBJECT --*/
    function generate() {
        var data = {};
        for (var prop in link) {
          data[prop] = link[prop];
        }
        data = JSON.stringify(data);
        document.getElementById("output").innerHTML = data;
    }
    
    /* ---------- CLICK BUTTON --*/
    document.querySelector("button").onclick = function(event) {
        //Should not do long things in an event handler.
        //Thus, instead of actually performing the tests here, we set
        //  a timeout which will execute after the event has processed.
        this.style.display = 'none'; //Only get to click once
        setTimeout(performTimedTests,0,generate,result);
    }
    
    /*
     * Perform multiple runs of an increasing number of iterations of a specified function.
     *   
     *   functionToTest = The function which is being timed
     *   resultsElement = An element in the DOM, usually a <div>, which will
     *                    have its innerHTML replaced with a table of time results.
     *   start =  The number of iterations to start with. (default = 1)
     *   end   =  The number of iterations to not exceed. (default = 1000000)
     *   multiplier = The amount multiply the current number of iterations to find
     *                  the number of iterations for the next run. (default = 10)
     */
    function performTimedTests(functionToTest,resultsElement,start,end,multiplier){
        start=start?start:1;
        end=end?end:1000000;
        multiplier=multiplier?multiplier:10;
        var textColors =['red','orange','yellow','green','blue','purple']
        
        function timeAfunction(functionToTest, iterations){
            var i, startTime, endTime;
            startTime = window.performance.now();
            for(i=0;i<iterations;i++){
                functionToTest();
            }
            endTime = window.performance.now();
            return (endTime - startTime);
        }
    
        function addResultToTable(table, elapsedTime, iterations, precision1, units1
                                  , precision2, units2, scale2, name) {
            var perCall = (elapsedTime/iterations)*scale2;
            var newRow = table.insertRow(-1);
            newRow.insertCell(-1).textContent = iterations;
            newRow.insertCell(-1).textContent = elapsedTime.toFixed(precision1) + units1;
            newRow.insertCell(-1).textContent = perCall.toFixed(precision2) + units2;
            newRow.insertCell(-1).textContent = name;
        }
    
    
        function performNextTest(functionToTest,resultsElement,iterations,maxIterations
                                 ,multiplier,isFirstIteration){
            var elapsedTime = timeAfunction(functionToTest, iterations);
            var processing;
            if(isFirstIteration) {
                result.innerHTML = '<div></div>'
                                   +'<table><tr><th>Iterations</th><th>Total time</th>'
                                   +'<th>Time per<br/>Iteration</th>'
                                   +'<th>Function<br>Tested</th></tr></table>';
                processing = resultsElement.querySelector('div');
                processing.textContent = 'Processing';
                processing.style.color = textColors[0];
            }
            processing = resultsElement.querySelector('div');
            var table = resultsElement.querySelector('table');
            addResultToTable(table,elapsedTime,iterations,3,'ms',3,'us',1000
                             ,functionToTest.name);
            processing.textContent += '.';
            //Cycle colors of 'Processing..' text
            var colorIndex=textColors.indexOf(processing.style.color);
            colorIndex++;
            colorIndex = colorIndex>=textColors.length?0:colorIndex;
            processing.style.color = textColors[colorIndex];
            iterations *= multiplier;
            if(iterations<=maxIterations) {
                //Let the browser redraw
                setTimeout(performNextTest,0,functionToTest,resultsElement,iterations
                           ,maxIterations,multiplier,false);
            }else{
                processing.textContent = '';
                processing.style.display = 'none';
            }
        }
    
        performNextTest(functionToTest,resultsElement,start,end,multiplier,true);
    }
    <button>Start</button>
    <div id="result"></div>
    <div id="output"></div>