【问题标题】:Why does my code not work in Safari or Opera?为什么我的代码在 Safari 或 Opera 中不起作用?
【发布时间】:2017-07-18 20:03:01
【问题描述】:

js 中有一个函数可以向表格显示消息(消息存储在json 中)。在 Google Chrome 中,它可以工作,但 Safari、Opera 或 Microsoft Edge - 不行! 与对setTimeout (callback, 5000) 的调用相关的代码中存在错误(没有任何内容发送到回调)。因此,For (var i = 0; i <respond.length; i ++) 将无法工作,因为respond === undefined

但为什么会这样呢?

callback(
  [{
      "time": "1500303264",
      "user": "qwe",
      "message": "we",
      "id": 1
    },
    {
      "time": "1500303987",
      "user": "Max",
      "message": "q",
      "id": 2
    }
  ]);

function smile(mess) {
  var smile = ":)";
  var graficSmile = "<img src = './image/Smile.png' alt='Smile' align='middle'>";
  var string_with_replaced_smile = mess.replace(smile, graficSmile);

  var sad = ":("
  var graficSad = "<img src = './image/Sad.png' alt='Smile' align='middle'>";
  var string_with_replaced_smile_and_sad = string_with_replaced_smile.replace(sad, graficSad);

  return string_with_replaced_smile_and_sad;
}

$.getJSON('data/messages.json', callback);
var exists = [];

function callback(respond) {
  var timeNow = Date.now();

  for (var i = 0; i < respond.length; i++) {
    var data = respond[i];

    if (exists.indexOf(data.id) != -1) continue;

    var timeInMessage = data.time * 1000;
    var diff_time = (timeNow - timeInMessage);

    if (diff_time <= 3600000) {
      var rowClone = $('.mess_hide').clone().removeClass('mess_hide');

      var newDate = new Date(timeInMessage);
      var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()]
      var res = dateArray.map(function(x) {
        return x < 10 ? "0" + x : x;
      }).join(":");

      $('#messages').append(rowClone);
      $('.time', rowClone).html(res);
      $('.name', rowClone).html(data.user);
      $('.message', rowClone).html(smile(data.message));
      $('.scroller').scrollTop($('#messages').height());

      exists.push(data.id);
    }
  }
  setTimeout(function(){callback(respond)}, 5000);
}
.scroller {
  width: 490px;
  height: 255px;
  max-height: 255px;
  overflow-y: auto;
  overflow-x: hidden;
}

table#messages {
  min-height: 260px;
  width: 100%;
  background: #fffecd;
  border: none;
}

table#messages::-webkit-scrollbar {
  width: 1em;
}

table#messages::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}

table#messages::-webkit-scrollbar-thumb {
  background-color: darkgrey;
  outline: 1px solid slategrey;
}

tr {
  height: 20%;
  display: block;
}

td.time,
td.name {
  width: 70px;
  max-width: 75px;
  text-align: center;
}

td.name {
  font-weight: bold;
}

form#text_submit {
  display: inline-flex;
  align-items: flex-start;
}

input#text {
  width: 370px;
  height: 30px;
  margin-top: 20px;
  background: #fffecd;
  font-family: 'Montserrat';
  font-size: 16px;
  border: none;
  align-self: flex-start;
}

input#submit {
  padding: 0;
  margin-left: 21px;
  margin-top: 21px;
  height: 30px;
  width: 95px;
  background: #635960;
  border: none;
  color: white;
  font-family: 'Montserrat';
  font-size: 16px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scroller">
  <table id="messages">
    <tr class="mess_hide">
      <td class="time"></td>
      <td class="name"></td>
      <td class="message"></td>
    </tr>
  </table>
</div>
<form method="POST" id="easyForm">
  <input type="text" name="text" id="text">
  <input type="submit" value="Send" id="submit">
</form>
</div>

歌剧

【问题讨论】:

    标签: javascript jquery google-chrome safari opera


    【解决方案1】:
    1. 由于假定var exists - 数组,但数组的值([])仅在调用$.getJSON(...) 之后才分配给它。因此,当第一次调用callback 时,没有为exists 设置值[]。我们只需将var exists 移动到callback. 的第一次调用之上
    2. callback 被定时器调用时,没有任何东西传递给它。但是计时器需要重新读取文件中的消息并将它们显示在屏幕上。所以,我们需要setTimeout(function(){callback(respond)}, 5000); 而不是setTimeout(function(){$.getJSON('data/messages.json', callback);}, 5000);

    var exists = [];
    $.getJSON('data/messages.json', callback);
    
    function callback(respond) {
      var timeNow = Date.now();
    
      for (var i = 0; i < respond.length; i++) {
        var data = respond[i];
    
        if (exists.indexOf(data.id) != -1) continue;
    
        var timeInMessage = data.time * 1000;
        var diff_time = (timeNow - timeInMessage);
    
        if (diff_time <= 3600000) {
          var rowClone = $('.mess_hide').clone().removeClass('mess_hide');
    
          var newDate = new Date(timeInMessage);
          var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()]
          var res = dateArray.map(function(x) {
            return x < 10 ? "0" + x : x;
          }).join(":");
    
          $('#messages').append(rowClone);
          $('.time', rowClone).html(res);
          $('.name', rowClone).html(data.user);
          $('.message', rowClone).html(smile(data.message));
          $('.scroller').scrollTop($('#messages').height());
    
          exists.push(data.id);
        }
      }
      setTimeout(function() {
        $.getJSON('data/messages.json', callback);
      }, 5000);
    }

    【讨论】:

    • 您能否为任何不擅长的人解释您的答案,只是说您添加了超时以及原因。
    • @MartinBarker 是的。看新答案。
    【解决方案2】:

    由于callback 要求将数组作为参数传递,setTimeout 必须确保在调用callback 时传递数组。

    改变

    setTimeout(callback, 5000);

    setTimeout(function(){callback(respond)}, 5000);

    它允许使用参数作为匿名函数的主体调用回调,该匿名函数将由setTimeout 调用。

    另外,附带说明一下,如果您使用 respond.forEach() 而不是计数 for 循环,代码会更简洁:

       respond.forEach(function(data) {
    
        if (exists.indexOf(data.id) != -1) continue;
    
        var timeInMessage = data.time * 1000;
        var diff_time = (timeNow - timeInMessage);
    
        if (diff_time <= 3600000) {
          var rowClone = $('.mess_hide').clone().removeClass('mess_hide');
    
          var newDate = new Date(timeInMessage);
          var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()]
          var res = dateArray.map(function(x) {
            return x < 10 ? "0" + x : x;
          }).join(":");
    
          $('#messages').append(rowClone);
          $('.time', rowClone).html(res);
          $('.name', rowClone).html(data.user);
          $('.message', rowClone).html(smile(data.message));
          $('.scroller').scrollTop($('#messages').height());
    
          exists.push(data.id);
        }
      });
    

    【讨论】:

    • 我介绍了您的编辑,但现在代码已完全停止显示消息。虽然错误不存在)
    • 但是respond 的值应该从哪里来?在问题中代码的当前状态下,setTimeout() 传递了respond,但它没有在任何地方定义。 (看起来它应该是从$.getJSON() 调用中返回的,所以我不确定超时是如何计算的。
    • @Pointy 是的,但是如果这个没有出现怎么办?
    猜你喜欢
    • 1970-01-01
    • 2010-12-20
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2014-01-23
    相关资源
    最近更新 更多