超时未按预期工作

timeout not working as expected

我试图让按钮从默认值 'this Will Change' 更改为 'New message',然后每 2 秒更改为 'someButton',然后停止它点击一下。

到目前为止,我有这个代码:

var timeouts = [];

var someArray = {button: 'new Message', button: 'Some Btn'};

$(document).ready(function(){
var i = 2000;
$.each(someArray, function(index, value){
    timeouts.push(setTimeout(function(){
          $(index).html(value);
     },i));
     i = i + 2000;
});


$('#stop').click(function(){
    $.each(timeouts, function (_, id) {
       clearTimeout(id);
    });
    timeouts = [];
    $(button).html('Some Btn');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>

它似乎忽略了第一个 setTimeout() 或者超时不是 运行 在新消息索引上。然后当我按下点击按钮时,没有超时被清除?

任何帮助我将不胜感激。

更新:我想尽可能保持 jQuery 的方向,谢谢!

之所以跳过new Message是因为:

var someArray = {button: 'new Message', button: 'Some Btn'};

您的 someArray 是一个对象。因此,如果您有相同的 属性 名称,它将被覆盖并被解析为

var someArray = {button: 'Some Btn'};

只要使用合适的结构就可以了

var timeouts = [];

var someArray = [{
  type: "button",
  message: 'new Message',
}, {
  type: "button",
  message: 'Some Btn'
}];

$(document).ready(function() {
  var i = 2000;
  $.each(someArray, function(index, value) {
    timeouts.push(setTimeout(function() {
      $(value.type).html(value.message);
    }, i));
    i = i + 2000;
  });


  $('#stop').click(function() {
    $.each(timeouts, function(_, id) {
      clearTimeout(id);
    });
    timeouts = [];
    $(button).html('Some Btn');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
  This will change
</button>
<a id='stop' href='#'>Stop</a>

更新代码

我会这样写。基本变化很少,

  • 使用 $(document).ready 作为代码流的开始。不作为您的代码的包装器。它应该调用必要的功能。
  • 您应该使用 Array.mapArray.forEach 而不是 $.each()。这些功能非常强大和好用。
  • 在任何函数之外定义的变量将成为全局范围的一部分。污染全局范围是一种不好的做法。
  • 使用小功能。这样您就更有可能重用您的代码。任何可以在别处使用的代码都可以用作函数。

$(document).ready(function() {
  var someArray = [
    { type: "button", message: 'new Message', }, 
    { type: "button", message: 'Some Btn' }
  ];

  var timeouts = registerTimeouts(someArray);
  registerEvents(timeouts)
});

function registerTimeouts(array) {
  return array.map(function(value, index) {
    return setTimeout(function() {
      $(value.type).html(value.message);
    }, (index + 1) * 2000);
  });
}

function registerEvents(timeouts) {
  $('#stop').click(function() {
    timeouts.forEach(function(id) {
      clearTimeout(id);
    });
    timeouts = [];
    $(button).html('Some Btn');
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
  This will change
</button>
<a id='stop' href='#'>Stop</a>

您的用例准确描述了 setInterval 的用途。

"Repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. Returns an intervalID."

setInterval 函数 returns 一个 ID,可以将其传递到 clearInterval 以停止代码每 X 秒 执行一次。

我已经发布了一个代码片段来说明我认为你正在努力实现的目标。

Plnkr Link

var strings = ["This will change", "Some button"];
var intervalID;
var button;
var index = 0;

$(document).ready(function() {
  button = $("#myButton");
  intervalID = window.setInterval(function() {
    console.log("hi");
    button.html(strings[index]);
    index = (index == 1 ? 0 : 1);
  }, 2000);
  $("#stop").click(function() {
    window.clearInterval(intervalID);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="myButton" type='button'>
  This will change
</button>
<a id='stop' href='#'>Stop</a>

这是一种干净、实用的方法。纯属娱乐。

所选答案正确。我只是提供另一种选择,使用稍微不同的风格。

它启动、切换和停止。

// "constant" array of messages
var messagesArray = ['new Message', 'Some Btn'];

// original button text
var btnOrigText = $('button').text()

// reverse an array
var _arrReverse = function(arr) {
    return arr.reverse()
}

// insert text from array 0th index into an element
var _insertTextArrayZero = function(el, messages) {
    // inserts an array's 0th index as HTML to an element
    return $(el).html(messages[0]);
}

// clears a timeout when given an id
var _clearIntvlAt = function(intvlId) {
    return clearTimeout(intvlId); 
}

$(document).ready(function(){
    // set interval
    var intvl = 2000;
    // keep our original array intact
    var messagesCloned = messagesArray.slice(0)
    // run interval
    var toggleTextIntvl = setInterval(function() {
     // insert reversed array from [0] index of array into HTML element
        // NOTE: this only works for arrays of 2 items which need to toggle
     return _insertTextArrayZero('button', _arrReverse(messagesCloned))
    }, intvl);
     
    // initiate "stopping" of toggle text
    $('#stop').click(function() {
        // stop toggleTextIntvl
        _clearIntvlAt(toggleTextIntvl)
        // set markup back to default
        $('button').html(btnOrigText);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type='button'>
This will change
</button>
<a id='stop' href='#'>Stop</a>