Javascript Safari在confirm()方法之前没有运行行

时间:2016-06-05 08:31:23

标签: javascript html safari

这实际上是Head First JavaScript ch05一书中的一个例子。我对Firefox中的代码没有问题,但Safari,我不确定问题出在哪里。

<html>
  <head>
    <title>Mandango - The Macho Movie Ticket Finder</title>

    <script type="text/javascript">
      var seats = [ false, true, false, true, true, true, false, true, false ];
      var selSeat = -1;

      function initSeats() {
        // Initialize the appearance of all seats
        for (var i = 0; i < seats.length; i++) {
          if (seats[i]) {
            // Set the seat to available
            document.getElementById("seat" + i).src = "seat_avail.png";
            document.getElementById("seat" + i).alt = "Available seat";
          }
          else {
            // Set the seat to unavailable
            document.getElementById("seat" + i).src = "seat_unavail.png";
            document.getElementById("seat" + i).alt = "Unavailable seat";
          }
        }
      }

      function findSeat() {
        // If seat is already selected, reinitialize all seats to clear them
        if (selSeat >= 0) {
          selSeat = -1;
          initSeats();
        }

        // Search through all the seats for availability
        for (var i = 0; i < seats.length; i++) {
          // See if the current seat is available
          if (seats[i]) {
            // Set the seat selection and update the appearance of the seat
            selSeat = i;
            document.getElementById("seat" + i).src = "seat_select.png";
            document.getElementById("seat" + i).alt = "Your seat";

            // Prompt the user to accept the seat
            var accept = confirm("Seat " + (i + 1) + " is available. Accept?");
            if (accept) {
              // The user accepted the seat, so we're done
              break;
            }
            else {
              // The user rejected the seat, so clear the seat selection and keep looking
              selSeat = -1;
              document.getElementById("seat" + i).src = "seat_avail.png";
              document.getElementById("seat" + i).alt = "Available seat";
            }
          }
        }
      }
    </script>
  </head>

  <body onload="initSeats();">
    <div style="margin-top:75px; text-align:center">
      <img id="seat0" src="" alt="" />
      <img id="seat1" src="" alt="" />
      <img id="seat2" src="" alt="" />
      <img id="seat3" src="" alt="" />
      <img id="seat4" src="" alt="" />
      <img id="seat5" src="" alt="" />
      <img id="seat6" src="" alt="" />
      <img id="seat7" src="" alt="" />
      <img id="seat8" src="" alt="" /><br />
      <input type="button" id="findseat" value="Find Seat" onclick="findSeat();" />
    </div>
  </body>
</html>

它想要在座位上寻找可用(真实)座位,更新座位图像并通过确认方法询问用户。

问题是findSeat功能:

它与Firefox运行完美,但是当我在Safari(版本9.1)中运行它时,在我在确认框中单击“确定”之前座位图像不会更新。即,在确认方法返回True之前,代码将不会运行。

  

document.getElementById(“seat”+ i).src =“seat_select.png”

     

document.getElementById(“seat”+ i).alt =“你的座位”

我猜这是确认方法的问题。有人可以帮忙吗?谢谢。

seat_select.png seat_select.png

seat_avail.png seat_avail

seat_unavail.png seat_unavail

2 个答案:

答案 0 :(得分:1)

浏览器上的JavaScript使用单个UI线程 1 运行,这可能(取决于浏览器体系结构)除了运行JavaScript之外还有其他工作,通常是与UI相关的任务,如更新图像。

confirm方法(及其表兄alert)使该线程在许多浏览器上暂停,阻止它执行任何操作,直到/除非用户解除对话框。

您引用的代码假定座位图像将与src的分配同步更新(不是安全的假设,特别是因为它可能必须下载)或者它会更新而confirm对话框正在显示(不是一个安全的假设)。

相反,代码应该在load元素上使用img事件回调,就像这个(很大程度上未经测试),请参阅注释:

function findSeat() {
  var seatDisplay;

  // If seat is already selected, reinitialize all seats to clear them
  if (selSeat >= 0) {
    selSeat = -1;
    initSeats();
  }

  // Find an available seat
  var availableSeat = null;
  seats.some(function(seat, index) {
    if (seat) {
      availableSeat = seat;
      selSeat = index;
      return true; // Stop looping
    }
  });
  if (availableSeat) {
    // Set the seat selection and update the appearance of the seat
    var seatDisplay = document.getElementById("seat" + selSeat);
    seatDisplay.src = "";
    seatDisplay.addEventListener("load", seatReady, false);
    seatdisplay.src = "seat_select.png";
    seatdisplay.alt = "Your seat";
  }

  function seatReady() {
    // Remove this handler
    seatDisplay.removeEventListener("load", seatReady, false);

    // Prompt the user to accept the seat
    var accept = confirm("Seat " + (selSeat + 1) + " is available. Accept?");
    if (accept) {
      // The user accepted the seat, so we're done
    }
    else {
      // The user rejected the seat, so clear the seat selection and keep looking
      selSeat = -1;
      seatDisplay.src = "seat_avail.png";
      seatDisplay.alt = "Available seat";
    }
  }
}

他们可能没有这样做,因为他们希望避免本书这一阶段的复杂性,但不幸的是,显然没有在不同的浏览器上进行充分测试,并且不知道可能的竞争条件。

1 &#34;浏览器上的JavaScript使用单个UI线程运行...&#34; 不是单一 - 因为你会听到人们不断声称的话。只有一个UI线程,但您可以使用web workers拥有任意数量的其他线程。

答案 1 :(得分:0)

在Safari中似乎存在一个错误,即在前面的代码有时间执行之前,确认方法会触发。一个解决方案seen here是在setTimeout回调函数中运行您的确认。

E.g

var accept;

function doConfirm() {
    accept = confirm("Seat " + (i + 1) + " is available. Accept?");
}

// run the confirm after 200ms
window.setTimeout(doConfirm(), 200);