函数使用setInterval调用自身(浏览器冻结问题)

时间:2016-10-29 23:19:49

标签: javascript function setinterval

我知道我的问题已经存在,但我读到的答案都没有解决我的问题。

我写了一个小脚本,使用两个函数逐字母打印一个字符串:第一个拼写字符串,第二个使用setInterval调用第一个字符串,只要该单词不完全拼写:

function write() {
  writeThis = str.substring(0, currentLetter);
  div.innerHTML = writeThis;
  currentLetter++;
  console.log('running'); 
}

function start() {
  setInterval(function() {
    if (currentLetter > str.length) {
        return false;
    }
    write(); //calls the writing function
  }, 100);
}
start();

我需要将这两个函数合并为一个,以便通过将字符串作为参数传递,在不同的字符串上动态使用它。我正在尝试做这样的事情:

function write(thisString) {
  //code
  return thisString;
}
var str1 = "hello world";
var str2 = "foo bar";
write(str1); write(str2);

setInterval函数中插入write()以调用自身时,我感到困惑。无论我尝试什么write()都会永远自称(尽管if条件)并冻结浏览器。是否可以将这两个函数合并为一个?

在这里演示:https://jsfiddle.net/Hal_9100/b5gm8nbc/

3 个答案:

答案 0 :(得分:0)

setInterval会一直开火,直到您拨打clearInterval(intervalId)

对于大多数动画,在任何情况下使用setTimeout都更容易控制,如下所示:

var div = document.getElementById('div');
var str = 'hello world.';
var currentLetter = 1;

var writeThis = str.substring(0, currentLetter);

function write() {
    writeThis = str.substring(0, currentLetter);
    div.innerHTML = writeThis;
    currentLetter++;
    console.log('running'); 
}

function run(){
    if (currentLetter > str.length) {
        return false;
    }
    write();
    setTimeout(run, 100);
}

function start() {
  setTimeout(run, 100);
}
start();

如果你真的想使用setInterval,该函数会返回你需要的intervalId,所以你可以这样做:

var intervalId = setInterval(fn, 100);

然后在if语句中,你打电话

clearInterval(intervalId);

显然,您需要确保intervalId在两个地方都在范围内。

**编辑**

添加一个功能。对不起,我错过了这部分问题。这里的诀窍是使用Function.bind()

var div = document.getElementById('div');
var str = 'hello world.';
var currentLetter = 1;

var writeThis = str.substring(0, currentLetter);

function run(text){
    if (currentLetter > text.length) {
        return false;
    }
    writeThis = text.substring(0, currentLetter);
    div.innerHTML = writeThis;
    currentLetter++;
    console.log('running');
    setTimeout(run.bind(null, text), 100);
}

run(str);

如果你想传递所有内容(例如div,str,当前字母),只需将它们作为参数添加到run函数中,并在再次绑定时添加它们。

答案 1 :(得分:0)

以下是使用Element.typeEffect("Hello World");

的示例原型

更新:最好使用textContent代替innerHTML将字符串写为文字而不是HTML。

<强>点数:

  • 如果要使用具有多个div的函数
  • ,请避免使用递增数作为全局变量
  • 在使用此功能之前,您的#div应为空。
  • 完成书写后,您可以使用回调。

&#13;
&#13;
var div = document.getElementById('div');
var div2 = document.getElementById('div2');

Element.prototype.typeEffect = function(str, onfinish) {
  var el = this;
  var i = el.textContent || el.innerText;
  i = i.length;
  if (i == str.length) {
    if (typeof onfinish == "function") onfinish();
    return;
  }

  el.textContent += str[i];
  setTimeout(function() {
    el.typeEffect(str, onfinish);
  }, 100);

}

div.typeEffect("Hello World");
//optinaly callback
div2.typeEffect("Helo Again", function() {
  console.log("#div2 finished");
});
&#13;
<div id="div"></div>
<hr/>
<div id="div2"></div>
&#13;
&#13;
&#13;

如果你不喜欢原型,试试这个

function typeEffect(str,el,cb) {
  var i = el.textContent || el.innerText;
  i = i.length;
  if (i == str.length){
  if(typeof cb == "function")cb();
    return;    
  }
  el.textContent += str[i];
  setTimeout(function() {
    typeEffect(str,el,cb);
  }, 100);

}
//usage
typeEffect("Hello World",div);
//or with callback
typeEffect("Hello World",div,function(){
console.log("finished");
});

答案 2 :(得分:0)

如果您使用setInterval(),则必须使用clearInterval()清除间隔。

结构

var interval = setInterval(function() {
    var i = 0;
    if(i < x) {
        ...
    } else {
        clearInterval(interval);
    }
});

总计:

var div = document.getElementById("myDiv");
var str = "Hello world!";

function write(str) {
  var i = 0;
  var len = str.length;
  var interval = setInterval(function() {
    if (i < len) {
      div.innerHTML += str[i];
    } else {
      clearInterval(interval);
    }
    i += 1;
  }, 100);
}

write(str);
<div id="myDiv"></div>