Có một hàm JavaScript, trong đó tôi không có quyền kiểm soát mã, gọi hàm mà tôi đã viết. Hàm của tôi sử dụng DOM để tạo một iFrame, định nghĩa nó là src và sau đó gắn nó vào một phần tử DOM khác. Tuy nhiên, trước khi hàm của tôi trả về, và do đó cho phép tiếp tục thực hiện hàm chứa, bắt buộc phải tải iFrame đầy đủ.Độ trễ/Javascript không thể nội tuyến không thể
Dưới đây là những điều mà tôi đã cố gắng và tại sao họ không làm việc:
1. Lựa chọn setTimeout:
99,999% thời gian, đây là câu trả lời. Thực tế, trong thập kỷ qua tôi đã cố vấn trong JavaScript, tôi đã luôn luôn nhấn mạnh rằng mã luôn có thể được tái cấu trúc để sử dụng tùy chọn này, và không bao giờ tin rằng một kịch bản tồn tại ở nơi không phải vậy. Vâng, cuối cùng tôi đã tìm thấy một! Vấn đề là bởi vì chức năng của tôi đang được gọi là inline, nếu dòng tiếp theo được thực hiện trước khi iFrame của tôi kết thúc tải, nó hoàn toàn trung lập kịch bản của tôi, và kể từ khi kịch bản của tôi hoàn thành, kịch bản bên ngoài tiếp tục. Gọi lại các loại sẽ không hoạt động
2. Vòng lặp "Không làm gì":
Tùy chọn này bạn sử dụng khi (// iFrame không được tải) {// do nothing}. Về lý thuyết, điều này sẽ không trở lại cho đến khi khung được nạp. Vấn đề là vì điều này hogs tất cả các nguồn lực, iFrame không bao giờ tải. Bí quyết này, mặc dù khủng khiếp không chuyên nghiệp, bẩn vv sẽ làm việc khi bạn chỉ cần một sự chậm trễ nội tuyến, nhưng kể từ khi tôi yêu cầu một chủ đề bên ngoài để hoàn thành, nó sẽ không.
Trong FF, sau một vài giây, nó tạm dừng kịch bản và một cảnh báo bật lên nói rằng có một kịch bản không phản hồi. Trong khi cảnh báo đó tăng, iFrame có thể tải, và sau đó chức năng của tôi có thể quay trở lại, nhưng có trình duyệt bị đóng băng trong 10 giây và sau đó yêu cầu người dùng loại bỏ một lỗi chính xác là không đi.
3. Mô hình đối thoại:
Tôi đã lấy cảm hứng từ một thực tế là FF cửa sổ bật lên cho phép iFrame để tải trong khi ngăn chặn việc thực hiện các chức năng, và suy nghĩ về nó, tôi nhận ra rằng đó là vì các phương thức đối thoại, là một cách tạm dừng thực hiện nhưng cho phép các chủ đề khác tiếp tục! Rực rỡ, vì vậy tôi quyết định thử các phương thức khác. Những thứ như alert() làm việc rất đẹp! Khi nó bật lên, ngay cả khi chỉ lên 1/10 giây, iFrame có thể hoàn thành và tất cả đều hoạt động tốt. Và chỉ trong trường hợp 1/10 giây không đủ, tôi có thể đặt đối thoại mô hình trong vòng lặp while từ giải pháp 2, và nó sẽ đảm bảo rằng iFrame được nạp đúng lúc. Ngọt phải không? Ngoại trừ một thực tế là bây giờ tôi phải bật lên một cuộc đối thoại rất không chuyên nghiệp cho người dùng để loại bỏ để chạy kịch bản của tôi. Tôi đã chiến đấu với bản thân mình về chi phí/lợi ích của hành động này, nhưng sau đó tôi gặp phải một tình huống mà mã của tôi được gọi là 10 lần trên một trang duy nhất! Phải loại bỏ 10 cảnh báo trước khi acessing một trang ?! Điều đó làm tôi nhớ đến những trang kiddie cuối thập niên 90 và không phải là một lựa chọn.
4. Một gazillion khác chậm trễ kịch bản trên mạng:
Có khoảng 10 jQuery chậm trễ hoặc ngủ chức năng, một số trong số họ thực sự khá khéo léo phát triển, nhưng không ai làm việc. Một vài lựa chọn nguyên mẫu, và một lần nữa, không có gì tôi tìm thấy có thể làm được! Hàng tá thư viện và khuôn khổ khác cho rằng họ có những gì tôi cần, nhưng tất cả họ đều âm mưu cho tôi hy vọng sai lầm.
Tôi tin rằng kể từ khi một cuộc đối thoại mô hình có thể dừng thực hiện, trong khi cho phép các chủ đề khác tiếp tục, phải có một số cách có thể truy cập mã để làm điều tương tự với đầu vào của người dùng.
Mã theo nghĩa đen là hàng ngàn hàng ngàn dòng và là độc quyền, vì vậy tôi đã viết ví dụ nhỏ về vấn đề này để bạn làm việc cùng.Điều quan trọng cần lưu ý các mã chỉ bạn có thể thay đổi là trong hàm onlyThingYouCanChange
Kiểm tra File:
<html>
<head>
</head>
</html>
<body>
<div id='iFrameHolder'></div>
<script type='text/javascript'>
function unChangeableFunction()
{
new_iFrame = onlyThingYouCanChange(document.getElementById('iFrameHolder'));
new_iFrame_doc = (new_iFrame.contentWindow || new_iFrame.contentDocument);
if(new_iFrame_doc.document)new_iFrame_doc=new_iFrame_doc.document;
new_iFrame_body = new_iFrame_doc.body;
if(new_iFrame_body.innerHTML != 'Loaded?')
{
//The world explodes!!!
alert('you just blew up the world! Way to go!');
}
else
{
alert('wow, you did it! Way to go!');
}
}
var iFrameLoaded = false;
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
unChangeableFunction();
</script>
</body>
blank_frame.html:
<html>
<head>
</head>
<body style='margin:0px'>Loaded?</body>
</html>
ĐÂY LÀ ĐÁP tôi THỰC HIỆN TỪ CÁC LÝ TƯỞNG TỪ KHI ĐẾN TÁC GIẢ! BẠN GUYS ROCK!
nguồn mới của hàm tôi được phép thay đổi:
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
if (window.XMLHttpRequest)
{
AJAX=new XMLHttpRequest();
}
else
{
AJAX=new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX)
{
AJAX.open("GET", 'slow_page.php', false);
AJAX.send(null);
}
else
{
alert('something is wrong with AJAX!');
}
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
slow_page.php:
<?
usleep(100000);//sleep for 1/10th of a second, to allow iFrame time to load without DOSing our own server!
?>
tôi muốn lưu ý rằng tôi nói rằng chẳng có gì ngoài chức năng đó mà tôi có thể thay đổi và thêm trang php đã vi phạm "quy tắc" đó nhưng trong trường hợp này tôi có thể làm điều đó. Nếu tôi không thể làm điều đó, tôi có thể đã được gọi là blank_frame.html thay vì slow_page.php và chỉ cần bao giờ cần gọi nó một lần (vì vậy 2 lần cho mỗi lần tải khung) giả định rằng nó phản hồi trong một lượng thời gian khi tải iFrame. Nếu vì lý do nào đó, tải iFrame chậm hơn, có thể gọi là 2ce (tổng số 3 cuộc gọi đến máy chủ)
Bạn không thể kết hợp 'hàm mới() {return code; } 'với gọi lại của' setTimeout'? –
Cá nhân tôi nghĩ rằng bất kỳ thiết kế nào yêu cầu trường hợp này là rất thiếu sót, nhưng từ góc độ học thuật, tôi muốn được quan tâm xem liệu có câu trả lời hay không. –
meder, setTimeout sẽ cho phép thực thi Javascript liên tục, trừ khi bạn có cách kết hợp những thứ mà tôi không biết. Tôi đã đề cập đến một số plugin jQuery đã làm một số điều rất thông minh, với điều đó, nhưng tôi phân tích tất cả những gì tôi có thể tìm thấy và không có gì sẽ làm việc cho tôi. Nếu bạn có thể tìm cách để làm cho nó hoạt động trong ví dụ trên, tôi sẽ rất vui mừng! Brian. Tôi đồng ý với bạn 99,999%, và một vài ngày trước tôi đã nói 100%, và sẽ tranh cãi với bất cứ ai nói rằng sự trì hoãn nội tuyến là cần thiết. Thật không may tôi không có quyền kiểm soát để sửa nó ở đây! – trex005