为什么我的代码在Safari和Opera中无法运行?

13
在js中有一个函数可以显示存储在json中的消息到表格上。在谷歌浏览器中,它可以正常工作,但是在Safari、Opera或Microsoft Edge中却不行!代码中存在一个与setTimeout(callback,5000)的调用相关联的错误(没有发送任何内容到回调函数)。因此,由于respond === undefined,For (var i = 0; i <respond.length; i ++)将无法工作。 但为什么会这样呢?

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>

Chrome Chrome

Opera Opera

2个回答

13
  1. 假设数组var exists已存在,但在调用$.getJSON(...)之后才将值([])赋给它。因此,当第一次调用callback时,exists的值[]尚未设置。我们只需要将var exists移至callback的第一次调用之前。
  2. 当计时器调用callback时,不传递任何参数。但计时器需要重新读取文件中的消息并在屏幕上显示它们。因此,我们需要使用setTimeout(function(){$.getJSON('data/messages.json', callback);}, 5000);代替setTimeout(function(){callback(respond)}, 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);
}


你能否解释一下你的答案,以便于那些不熟练的人理解?只需要说明你添加了一个超时时间和原因即可。 - Barkermn01
1
@MartinBarker 是的。看看新的回答。 - Tick-Tack

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

我已经引入了你的修改,但现在代码完全停止显示消息了(尽管错误并不存在)。 - Tick-Tack
但是 respond 的值应该从哪里来呢?在问题的当前代码状态中,setTimeout() 传递了 respond,但它没有在任何地方定义。 (看起来它应该从 $.getJSON() 调用返回,所以我不确定超时机制如何发挥作用。) - Pointy
@Pointy 是的,但如果这个没有出现,有什么问题吗? - Tick-Tack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接