为什么我的代码在Safari或Opera中不起作用?

时间:2017-07-18 20:03:02

标签: javascript jquery google-chrome safari opera

js中有一个功能可以向表中显示消息(消息存储在json中)。在谷歌浏览器中,它可以运行,但Safari,Opera或Microsoft Edge - 不! 代码中存在与调用setTimeout (callback, 5000)相关联的错误(没有任何内容发送到回调)。因此,For (var i = 0; i <respond.length; i ++)respond === undefined起无法正常工作。

但为什么会如此?

&#13;
&#13;
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);
}
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

Chrome

歌剧 Opera

2 个答案:

答案 0 :(得分:13)

  1. 由于假设var exists - 数组,但数组([])的值仅在稍后调用$.getJSON(...)之后才被分配给它。因此,第一次调用callback时,[]未设置值exists。我们只需将var exists移到callback.的第一次调用之上
  2. 当计时器调用callback时,没有任何内容传递给它。但是计时器需要重新读取文件中的消息并将其显示在屏幕上。相反,setTimeout(function(){callback(respond)}, 5000);我们需要setTimeout(function(){$.getJSON('data/messages.json', callback);}, 5000);
  3. 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);
    }

答案 1 :(得分:5)

由于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);
    }
  });