所以我的问题是超时, 因为到它开始时,我的数组被重置,所有其他值也被更改。
我在message数组中输入了用户输入的内容,这是他们输入的行。 例如:
messages = ["first line", "second", "third", "etc.."];
for(var i=0; i < messages.length; i++){
setTimeout(function () {
draw(messages[i], x, y+(i*k*f) );
}, i*20*messages[i].length);
}
message = "";
messages = [];
k
和f
分别是常数值3
和2
,但是用户可以将其更改为任何浮点值。 x
和y
是一些坐标。
因此,一旦调用draw()
函数,则值是不确定的或错误的。
我已经搜索了一些答案,但是没有一个答案足以让我弄清楚我需要为特定案例做些什么。
答案 0 :(得分:7)
您的for循环根据示例messages
的长度执行4次。但是,当第一个setTimeout
结束并触发其中的匿名函数时,messages
数组在后面的代码行中已经为空。
在最后一行代码中,您将messages
数组重新初始化为空数组,并且在异步setTimeout
回调发生时,它们正在尝试访问索引0,1, 2,3不再存在,因此结果是未定义的值。
messages = []; // an empty array with zero length
为帮助弄清正在发生的事情,请考虑以下问题:
// this is what you might expect
var arr = [ "foo", "bar", "baz"];
console.log(arr[0]); // logs "foo" to the console
// this is actually what's happening
var arr = []; // set arr equal to a new empty array
console.log(arr[0]); // logs "undefined" to the console
我只解释了原因和原因。 @brk在回答中提供了两种代码解决方案。
答案 1 :(得分:2)
在Javascript setTimeout
中,函数是异步的。所以您的以下代码
messages = [];
它在实际超时回调函数被调用之前执行,您会看到错误,因为在实际回调函数被调用时messages
变量为空。
尝试了解有关异步Java脚本的更多信息,您会更好地理解。
答案 2 :(得分:2)
创建一个闭包和一个立即调用的函数表达式,并在settimeout回调函数内部传递变量以对其进行访问
Integer.to_string(43981, 16) # "ABCD"
此Integer.to_string(43981, 2) # "1010101111001101"
Integer.to_string(43981, 8) # "125715"
关键字的替代用法。用let关键字声明的变量在当前块中始终具有作用域
let messages = ["first line", "second", "third", "etc.."];
for (var i = 0; i < messages.length; i++) {
//Creating an IIFE
(function(x, msg) {
//typical closure, passing x & message to the settimeout
setTimeout(function() {
draw(msg[x]);
}, x * 20 * msg[x].length);
}(i, messages)) // passing reference of both i, & messages
}
messages = "";
messages = [];
function draw(x, y, z) {
console.log(x)
}
答案 3 :(得分:1)
您正在尝试在setTimeout
中运行逻辑,并且变量i
是函数级。这意味着您的超时功能将在for循环和所有同步方法完成后执行。在您的情况下,您的超时功能将在最后一行messages=[]
之后执行,并且i
的值为messages.length
,即循环执行时的4
。
为避免此问题,请使用自动关闭功能。自闭包将把参数作为同步并存储不会改变的可变功能级别。
这是一个如何使用自我封闭的例子。
messages = ["first line", "second", "third", "etc.."];
for(var i=0; i < messages.length; i++){
(function(i, message) {
setTimeout(function () {
draw(message, x, y+(i*k*f) );
}, i*20*message.length);
})(i, messages[i])
}
message = "";
messages = [];
在此示例中,我们避免使用foor循环函数的变量,而是在循环内部创建新函数并传递参数。
答案 4 :(得分:0)
您必须保存当前值。
主要问题是variable's scope
,并且共享变量将被覆盖。
messages = ["first line", "second", "third", "etc.."];
// your variable
var x = 1;
var y = 1;
var k = 2;
var f = 3;
for(var i=0; i < messages.length; i++){
set(messages[i]);
}
message = "";
messages = [];
// set a function scope to save current value
function set(val){
setTimeout(function () {
draw(val, x, y+(i*k*f) );
}, i*20*val.length);
}
// your draw function
function draw(a, b, c){
console.log(a);
}