这实际上是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 =“你的座位”
我猜这是确认方法的问题。有人可以帮忙吗?谢谢。
答案 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);