2

我看到这个问题之前已经被问过,但我不确定我的问题的解决方案。

我有以下代码:

function mouseup (  )
{
    for( i = 0; i < 6; i++ )
    {
        setTimeout(function(){
            alert( "test" );
        },1000);
    } 
}

但是当我运行代码时,暂停一秒钟后,对话框出现(应该如此),但是当我在该对话框上单击确定时,第二个立即出现,没有任何延迟。

jsFiddle 示例

有没有一种简单的方法可以在不更改太多代码的情况下解决这个问题?我问的原因是因为我正在构建一个更改代码的转换器,例如:

repeat 6 times
    wait for 1 second
    answer "test"
end repeat

进入上面的 JavaScript 代码,如果我没有太多,不想改变太多我的转换器程序。

提前谢谢了。

编辑:(如果您想知道,非 JavaScript 代码是 HyperTalk/xTalk 代码)

4

8 回答 8

8
window.counter = 6;
function mouseup (  )
{
    setTimeout(function(){
        alert( "test" );
        if ( window.counter-- ) {
            mouseup (  );
        }
    },1000);
}
于 2014-04-04T14:21:34.610 回答
7

你不能用 for 循环来实现你想要的。for 循环在继续之前不会等待超时。为了做你想做的事,你需要将你的超时链接在一起,以便结束一个超时开始下一个:

var i = 0;
function TimeoutFired() {
    i++;
    alert( "test" );
    if (i < 6) {
        setTimeout(TimeoutFired, 1000);
    }
}
setTimeout(TimeoutFired, 1000);

http://jsfiddle.net/M98ZL/

于 2014-04-04T14:24:18.633 回答
2

与其他解决方案一样,您可以使用setInterval并在执行 6 次后清除它

function mouseup (  )
{
    var i=0;
    var myVar = setInterval(function(){

        alert("test")
        i++;
        if(i===6){clearInterval(myVar);}                      
    },1000);

}

演示

于 2014-04-04T14:25:00.093 回答
1
function mouseup (  )
{
    var delay = 0;
    for( i = 0; i < 6; i++ )
    {
        setTimeout(function(){
            alert( "test" );
        },(delay += 1000));
    } 
}
于 2014-04-04T14:21:52.450 回答
1

虽然这里已经有一些解决方案,但我想展示一些其他的解决方法。(此代码不会测试错误,只是让您知道可以做什么)

 function loop( from, to, callback, finished ) {
   var currIdx = from-1;

   function next() {
     currIdx++;
     if( currIdx < to ) {
       callback(currIdx, next, stop);
     } else {
       if( finished ) {
         finished();
       }
     }
   }

   function stop() {
     if( finished ) {
       finished();
     }
   }
   next();


 }


 loop( 0, 6, function( i, next, stop ) {
   console.log(i);

   setTimeout(function() {
     next();
   }, 1000);

 });

这将允许您将next和/或stop回调传递给其他函数,从而允许您以简单的方式使用异步代码创建循环。对于更复杂的事情,我建议也看看像whenjs这样的 Promise 库。

于 2014-04-04T14:59:23.400 回答
0
You can do this in three different ways


1. with IIFE
------------

let fruits = ["banana", "apple", "Orange"];

for (let index = 0; index < fruits.length; index++) {
  (function(fruits, index) {
    setTimeout(() => {
      console.log(fruits[index]);
    }, index * 1000);
  })(fruits, index);
}



2. with Closure, as it reference the outer scope variable even after 
      the main function execution
----------------------------------

let fruits = ["banana", "apple", "Orange"];
function closerWithsettimeout() {
    return function() {
        fruits.forEach(function(elem, i) {
            setTimeout(() => {
                console.log(elem);
            }, 1000 * i);
        });
    };
}
closerWithsettimeout()();



3. With promise
----------------
let fruits = ["banana", "apple", "Orange"];

fruits.forEach((elem, i) => {
  var p = new Promise((resolve, reject) => {
    fruits[0] === "banana" ?
      setTimeout(() => {
        resolve(elem);
      }, i * 1000) :
      reject(new Error("Fruits cannot be bought"));
  });
  p.then(result => console.log(result)).catch(err => console.log(err.message));
});
于 2019-01-07T03:32:12.673 回答
0

这个问题现在已经有了多个很好的答案,但由于没有一个提到async-await,我想提出一个使用它的解决方案。如果您的目标是对原始代码进行尽可能少的更改,那么没有比这更好的了。

async function mouseup (  )
{
    for( i = 0; i < 6; i++ )
    {
        await new Promise(function(resolve) {
            setTimeout(function(){
                alert( "test" );
                resolve();
            },1000);
        });
    } 
}
于 2019-01-07T04:01:40.077 回答
0

这个问题是由于 HyperTalk 允许您编写脚本命令以按顺序执行,而 JavaScript 仅按顺序触发它们。

从 ES7 开始,JavaScript 现在可以让您使用 async/await 顺序执行代码。

转换示例:

// Procedure to invoke upon mouseUp //
async function mouseup() {
    for( i = 0; i < 6; i++ ) {
        await myscript();
    } 
}

// Script to be invoked inside the for loop //
async function myscript() {
    setTimeout(function(){
        alert( "test" );
    },1000);
}

// Note: this does not include error trapping

请注意,使用 JavaScript,您需要捕获 mouseUp 事件(不等同于仅将其放入对象的脚本中以通过内置陷阱触发,如在 HyperCard 中)。

以前的 JavaScript 实践是在 DOM 元素(例如按钮)中引用单个事件触发器,但当前的实践是在一般侦听器中捕获它。有几种方法可以做到这一点(例如,从元素 ID 中监听“点击”事件,或者监听更高级项目的气泡并仅过滤来自您选择的元素的项目)。

可以在https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener中找到侦听 JavaScript 单击或(如果您愿意,可以使用鼠标)的语法

于 2020-08-24T15:05:37.677 回答