2010-02-17 44 views
5

tôi cần phải làm một cái gì đó như thế này:Javascript khối kịch bản thực hiện

  • Thực hiện một đoạn mã
  • Start để tải một hình ảnh và chặn các kịch bản thực hiện
  • Khi hình ảnh được nạp hồ sơ thực hiện
  • Execute phần còn lại của mã

tôi biết rằng cách đơn giản nhất là gán một chức năng trên các sự kiện onload của hình ảnh một nd sau đó thực hiện phần còn lại của mã trong hàm, nhưng nếu có thể tôi muốn có một hành vi "tuyến tính" chặn việc thực thi kịch bản và sau đó tiếp tục nó. Vậy, có cách nào để thực hiện điều này không?

Trả lời

3

Cách duy nhất để ngăn chặn thực thi kịch bản là sử dụng một vòng lặp, mà cũng sẽ bị khóa hầu hết các trình duyệt và ngăn chặn bất kỳ tương tác nào với trang web của bạn.

Firefox, Chrome, Safari, Opera và IE tất cả hỗ trợ thuộc tính complete, được chuẩn hóa cuối cùng trong HTML5. Điều này có nghĩa là bạn có thể sử dụng vòng lặp while để tạm dừng thực thi tập lệnh cho đến khi hình ảnh hoàn tất tải xuống.

var img = new Image(); 
img.src = "/myImage.jpg"; 
document.body.appendChild(img); 
while (!img.complete) 
{ 
    // do nothing... 
} 

// script continues after image load 

Điều đó đang được nói, tôi nghĩ bạn nên xem xét cách đạt được mục tiêu mà không cần khóa trình duyệt.

+0

Tôi đồng ý rằng đây là một cách xấu nhưng tôi cũng nghĩ rằng đó là cách duy nhất. Có lẽ tôi có thể cung cấp cho người dùng khả năng lựa chọn giữa việc chặn thực thi tập lệnh và gọi hàm tải khi hình ảnh được tải. – mck89

+0

@ mck89: Tôi thấy khó tin rằng đó là cách duy nhất. Tôi có thể thành thật nói rằng tôi chưa bao giờ gặp một tình huống trong JavaScript yêu cầu khóa kịch bản; luôn luôn có một cách (chẳng hạn như các hàm ghi đè tạm thời) để thực hiện mọi thứ một cách không đồng bộ. Bạn hoàn toàn kiểm soát được tập lệnh trên trang của mình. Có lẽ bạn có thể đăng một câu hỏi khác đi vào chi tiết hơn về vấn đề của bạn? –

+0

@ mck89: Thuộc tính 'complete' tồn tại cho Gecko và IE và cũng có thể hoạt động trên các trình duyệt khác. Nếu bạn khăng khăng chặn việc thực thi tập lệnh, hãy xem cập nhật của tôi. –

1

Nếu bạn không nhớ có một bước tiền xử lý, hãy thử Narrative Javascript, mà bạn có thể

image.onload = new EventNotifier(); 
image.onload.wait->(); 
+0

Đó là một dự án tuyệt vời nhưng tôi đang cố gắng xây dựng một ứng dụng đơn giản trong javascript thuần túy ... và tôi không biết gì về Java :) – mck89

+0

@ mck89: Sau khi tiền xử lý bạn nhận được Javascript thuần túy. – kennytm

+0

Vâng, tôi biết nhưng tôi thích chỉ sử dụng javascript – mck89

1

Đề xuất này không chính xác những gì bạn đã yêu cầu, nhưng tôi cung cấp đề xuất đó làm phương án có thể thay thế.

Tạo lớp CSS với hình nền bạn muốn sử dụng. Khi ứng dụng của bạn bắt đầu, hãy gán lớp CSS này cho DIV bị ẩn khỏi trang web hoặc được định kích thước bằng 0 bằng 0 pixel. Điều này sẽ đảm bảo hình ảnh được tải từ máy chủ. Khi bạn muốn tải hình ảnh (bước hai ở trên), sử dụng lớp CSS bạn tạo; điều này sẽ xảy ra nhanh chóng. Có thể đủ nhanh để bạn không chặn việc thực thi mã tiếp theo?

+0

Có thể đây là phương pháp tải trước tốt cho hình ảnh nhưng tôi không tải hình ảnh ở đầu ứng dụng. – mck89

+0

Tôi hiểu, nhưng nếu bạn đã tạo một lớp CSS có thuộc tính background-image, gán lớp đó cho DIV giả, bạn sẽ tải hình ảnh ở đầu ứng dụng. – Upperstage

1

tôi sẽ không cố gắng để ngăn chặn thực thi kịch bản hoàn toàn, vì điều đó có thể làm cho trình duyệt làm chậm, hoặc thậm chí cảnh báo người dùng rằng một kịch bản là dùng quá lâu để thực thi.

Điều bạn có thể làm là 'tuyến tính hóa' mã của bạn bằng cách sử dụng các sự kiện để hoàn thành công việc. Bạn sẽ cần thêm thời gian vào chức năng vì hình ảnh có thể không bao giờ tải.

Ví dụ:

var _img = null; 
var _imgDelay = 0; 
var _finished = false; 

function startWork(){ 
    _img = document.createElement('img'); 
    _img.onload = onImgLoaded; 
    _img.src = 'yourimg.png'; 

    // append img tag to parent element here 

    // this is a time out function in case the img never loads, 
    // or the onload event never fires (which can happen in some browsers) 
    imgTimeout(); 
} 

function imgTimeout(){ 
    if (_img.complete){ 
     // img is really done loading 
     finishWork(); 
    } 
    else{ 
     // calls recursively waiting for the img to load 
     // increasing the wait time with each call, up to 12s 
     _imgDelay += 3000; 

     if (_imgDelay <= 12000){ // waits up to 30 seconds 
     setTimeout(imgTimeout, _imgDelay); 
     } 
     else{ 
     // img never loaded, recover here. 
     } 
    } 
} 

function onImgLoaded(){ 
    finishWork(); 
} 

function finishWork(){ 
    if (!_finished){ 
     // continue here 
     _finished = true; 
    } 
} 
+0

Bạn có chắc chắn rằng bạn có thể ngừng thực hiện với setTimeout? – mck89

+0

Điều này không ngừng thực thi mã, nó cho phép bạn đợi cho đến khi hình ảnh được tải xong trước khi bạn thực hiện thêm bất kỳ công việc nào. Bạn 'dừng' thực hiện thực thi mã của riêng bạn bằng cách di chuyển mã còn lại của bạn vào hàm finishWork. – FlashXSFX

1

Bạn có thể sử dụng XMLHttpRequest và sử dụng chế độ đồng bộ.

var url = "image.php?sleep=3"; 
var img = new Image; 
var sjax = new XMLHttpRequest(); 
img.src = url; 
sjax.open("GET", url, false); 
sjax.send(null); 
alert(img.complete); 

Bí quyết ở đây là chúng tôi tải cùng một hình ảnh hai lần, trước tiên bằng cách sử dụng đối tượng Image và cũng bằng cách sử dụng ajax ở chế độ đồng bộ. Đối tượng Image là không cần thiết, tôi chỉ giả định đó là cách bạn muốn tải nó. Điều quan trọng là mặc dù ajax hoàn thành, sau đó hình ảnh sẽ được tải xuống đầy đủ trong bộ nhớ cache của trình duyệt. Như vậy, hình ảnh cũng sẽ có sẵn để sử dụng bởi đối tượng Image.

Điều này giả định rằng hình ảnh được phân phối với tiêu đề http thân thiện với bộ nhớ cache. Nếu không, hành vi của nó có thể thay đổi trong các trình duyệt khác nhau.

Các vấn đề liên quan