Cho phép tải JavaScript không đồng bộ trong WordPress. Tải JavaScript không đồng bộ - tăng tốc độ tải trang

Các trang web hiện đại được tải rất nhiều tệp javascript. Điều này dẫn đến việc tải trang và hiển thị trang sau đó chậm hơn. Trong điều kiện tồi tệ nhất, người truy cập trang web phải đợi tới 30 giây.

Chúng tôi tăng tốc đang tải html trang

Sử dụng JavaScript hiện đại

Các trang web hiện đại được tải rất nhiều tệp javascript. Điều này dẫn đến việc tải trang và hiển thị trang sau đó chậm hơn. Trong điều kiện tồi tệ nhất (kết nối Internet chậm, nhiều tệp javascript), người truy cập trang web phải chờ tới 30 giây.

HTML được thiết kế theo cách một trang web tải bằng cách tải đồng bộ (từng dòng một) lần lượt tất cả các phần tử có trong mã HTML.

Có một giải pháp: đặt chuỗi Java ở cuối tài liệu html(do đó, chúng sẽ được tải sau khi toàn bộ trang được vẽ) và chỉ sau đó nội dung của các khối mới được hiển thị ở đúng vị trí. Nó được gọi là .

Tất cả các dự án nghiêm túc hiện nay đều đang cố gắng chuyển sang công nghệ mới lượt tải xuống. Hơn nữa, nó hoàn toàn dễ dàng.

Có một số cách tiếp cận. Tôi sẽ bắt đầu theo thứ tự.

< script src= "//www.site.ru/script.js" type= "text/javascript" >

Chuẩn HTML5 hỗ trợ khả năng tải tập lệnh không đồng bộ, điều này có thể tăng tốc đáng kể thời gian truy xuất trang tổng thể. Chỉ cần thêm async hoặc defer .

< script async src= "//www.site.ru/script.js" type= "text/javascript" >

< script defer src= "//www.site.ru/script.js" type= "text/javascript" >

Sự khác biệt giữa thuộc tính async và defer là gì?

Trong cả hai trường hợp, chúng tôi nhận được tải tập lệnh không đồng bộ. Sự khác biệt duy nhất là thời điểm tập lệnh bắt đầu thực thi. Tập lệnh có thuộc tính async sẽ được thực thi sớm nhất có thể sau tập lệnh đó hết chỗ, nhưng trước khi đối tượng cửa sổ được tải. Nếu thuộc tính defer được sử dụng, tập lệnh sẽ không vi phạm thứ tự thực thi của nó so với các tập lệnh khác và việc thực thi nó sẽ xảy ra sau khi trang được tải và phân tích cú pháp đầy đủ, nhưng trước sự kiện DOMContentLoaded của đối tượng tài liệu.

Thật không may, cơ chế này hiện không hoạt động trên tất cả các trình duyệt (đặc biệt là IE). Cũng sẽ không hoạt động nếu có dòng document.write trong tệp script.js.

Như tất cả các chuyên gia đều biết, Google trả tiền Đặc biệt chú ý tốc độ tải trang web và giảm tốc độ tải trang chậm kết quả tìm kiếm. Để trợ giúp, Google đã phát triển một tập lệnh đặc biệt mà bạn có thể sử dụng để tải javascript không đồng bộ.

Để sử dụng, chỉ cần thay thế

TRÊN

Và kết nối tập lệnh extsrc.js

Nó sẽ diễn ra như thế này:

< script src= "//extsrcjs.googlecode.com/svn/trunk/extsrc.js" > < script extsrc= "...." >

Thật không may, phương pháp này cũng không hoạt động đối với các tệp có document.write

Một phương pháp phổ quát cho tất cả các trình duyệt. Thậm chí còn hoạt động với document.write

Ở vị trí trên trang mà chúng ta cần hiển thị phần tử của mình, hãy tạo một khối div trống:

< div id= "script_block" class = "script_block" >

Ở cuối trang, trước khi chúng tôi chèn tập lệnh để tải tệp không đồng bộ:

< div id= "script_ad" class = "script_ad" style= "display:none;" >Đây là bất kỳ tập tin hoặc tập lệnh nào cần được tải.< script type= "text/javascript" >// di chuyển nó tới vị trí thực tài liệu hiển thị. getElementById("script_block" ). appendChild(document. getElementById("script_ad" ) ); // hiển thị tài liệu. getElementById("script_ad" ) . phong cách. hiển thị = "chặn";

Rất tiếc, trong các phiên bản IE cũ nhất (6 trở xuống), tải không đồng bộ không hoạt động, nhưng thực tế không còn những người dùng như vậy nữa. Tất cả các trình duyệt và dịch vụ khác đều sử dụng thành công tải tăng tốc trang web.

Chào hỏi những người bạn! Bạn có biết rằng Đang tải JavaScript là một trong những điểm nghẽn lớn nhất trong hiệu suất trang web? Hôm nay nhiệm vụ chính của tôi là giải thích script là gì và nó ảnh hưởng như thế nào đến tốc độ cũng như hiệu suất của trang web.

Trình duyệt tải thẻ tập lệnh sẽ dừng hiển thị trang cho đến khi tập lệnh được tải và thực thi. Trang bị chặn và trình duyệt không phản hồi hành động của người dùng trong vài giây. Thời gian trễ phụ thuộc vào nhiều yếu tố:

  • cấu hình,
  • Tốc độ kết nối Internet,
  • kích thước tập tin và những thứ khác...

Vì lý do này, công cụ phân tích tốc độ trang web Google PageSpeed ​​​​Insights khuyên bạn nên xóa khỏi đầu trang Mã JavaScript, chặn hiển thị của nó. Một cách tốt là đặt các tập lệnh ở cuối trang web, chẳng hạn như trước thẻ đóng hoặc thiết lập tải không đồng bộ.

Nếu mã tập lệnh ảnh hưởng đến việc hiển thị phần trên cùng của trang web, đừng đặt nó vào tập tin riêng biệt và nhúng trực tiếp vào HTML.

JS có thể thay đổi nội dung của trang web và thậm chí chuyển hướng đến một URL khác. Trong trường hợp này, việc nối script ở cuối tài liệu sẽ dẫn đến hiệu ứng “co giật” trang, tải mới hoặc thay đổi các thành phần hiện có ở trên cùng.

Áp dụng thuộc tính async và defer cho thẻ script

Hãy cùng tìm hiểu xem không đồng bộ và hoãn lại là gì Công việc JavaScript và sự khác biệt cơ bản giữa thuộc tính async và defer là gì. Nhưng trước hết chúng ta hãy nhìn vào trình tự xử lý tài liệu khi kết nối bình thường thẻ kịch bản.

1 < src = "example.js" >

TRONG ví dụ rõ ràng Tôi sẽ sử dụng như sau biểu tượng:

- xử lý trang
- tải tập lệnh
- thực thi tập lệnh

Do đó, trình tự xử lý xảy ra theo sơ đồ sau:

Quá trình phân tích mã HTML bị gián đoạn trong khi tập lệnh đang tải và thực thi, sau đó nó vẫn tiếp tục. Có sự chậm trễ trong việc hiển thị trang web.

thuộc tính trì hoãn

Thuộc tính defer cho phép trình duyệt bắt đầu tải xuống các tệp js song song mà không dừng quá trình xử lý trang. Chúng được thực thi sau phân tích đầy đủ mô hình đối tượng tài liệu (từ Tài liệu tiếng Anh Mô hình đối tượng, viết tắt DOM), với trình duyệt đảm bảo tính nhất quán dựa trên thứ tự các tệp được đưa vào.

1 < defer src = "example.js" >

thuộc tính không đồng bộ

Hỗ trợ thuộc tính async đã xuất hiện trong HTML5, nó cho phép trình duyệt tải xuống các tệp js song song và thực thi chúng ngay sau khi tải xuống mà không cần đợi phần còn lại của trang được xử lý.

1 < async src = "example.js" >

Sơ đồ trình tự xử lý:

Đây là bản tải xuống không đồng bộ. Thuộc tính này được khuyến nghị sử dụng trong các tập lệnh không có tác động đáng kể đến việc hiển thị tài liệu. Chúng bao gồm các quầy thu thập số liệu thống kê ( Google phân tích, Yandex Metrica), mã mạng quảng cáo ( Mạng quảng cáo Yandex, Google Adsense), nút mạng xã hội và như thế.

Tốc độ tải trang web là một trong những yếu tố xếp hạng trên Google.

Không đồng bộ Kết nối JavaScript Giảm thời gian tải trang do không có độ trễ. Ngoài ra, tôi khuyên bạn nên nén và hợp nhất các tệp js thành một, chẳng hạn như sử dụng phần mở rộng . Người dùng thích các trang web nhanh 😎

) Tôi đã viết về tác động của các tệp JavaScript đối với Đường dẫn kết xuất quan trọng (CRP).


JavaScript là tài nguyên chặn cho trình phân tích cú pháp. Điều này có nghĩa là JavaScript chặn việc phân tích cú pháp tài liệu HTML. Khi trình phân tích cú pháp chạm tới thẻ ‹script> (không quan trọng là bên trong hay bên ngoài), nó sẽ dừng lại, chọn tệp (nếu là bên ngoài) và chạy nó.

Hành vi này có thể có vấn đề nếu chúng tôi tải nhiều tệp JavaScript trên một trang vì nó làm tăng thời gian hiển thị lần đầu ngay cả khi tài liệu không thực sự phụ thuộc vào các tệp đó.


May mắn thay, phần tử này có hai thuộc tính, async và defer, cho phép chúng ta kiểm soát cách tải và thực thi các tệp bên ngoài.

Thực hiện bình thường

Trước khi hiểu sự khác biệt giữa hai thuộc tính này, chúng ta hãy xem điều gì sẽ xảy ra khi chúng vắng mặt. Như đã nêu trước đó, theo mặc định, các tệp JavaScript sẽ làm gián đoạn quá trình phân tích cú pháp tài liệu HTML cho đến khi chúng được nhận và thực thi.
Hãy lấy một ví dụ trong đó phần tử nằm ở đâu đó ở giữa trang:


... ... ....

Đây là điều sẽ xảy ra khi trình phân tích cú pháp xử lý tài liệu:

Quá trình phân tích cú pháp HTML bị tạm dừng cho đến khi tập lệnh được tải xuống và thực thi, do đó sẽ tăng lượng thời gian cho đến lần hiển thị đầu tiên.

thuộc tính không đồng bộ

Async được sử dụng để cho trình duyệt biết rằng tập lệnh Có lẽđược thực hiện không đồng bộ.
Trình phân tích cú pháp HTML không cần dừng lại khi đến thẻ để tải và thực thi. Việc thực thi có thể xảy ra sau khi tập lệnh được nhận song song với việc phân tích cú pháp tài liệu.



Thuộc tính chỉ khả dụng cho các tệp được kết nối bên ngoài. Nếu như tập tin bên ngoài có thuộc tính này, nó có thể được tải trong khi tài liệu HTML vẫn đang được phân tích cú pháp. Trình phân tích cú pháp sẽ tạm dừng để thực thi tập lệnh ngay khi tệp tập lệnh được tải.



thuộc tính trì hoãn

Thuộc tính defer cho trình duyệt biết rằng tập lệnh sẽ được thực thi sau khi tài liệu HTML được phân tích cú pháp hoàn toàn.



Giống như việc tải tập lệnh không đồng bộ, tệp có thể được tải trong khi tài liệu HTML đang được phân tích cú pháp. Tuy nhiên, ngay cả khi tệp tập lệnh được tải đầy đủ trước khi trình phân tích cú pháp kết thúc, nó sẽ không được thực thi cho đến khi trình phân tích cú pháp chạy xong.



Thực thi không đồng bộ, bị trì hoãn hoặc bình thường?

Vậy khi nào bạn nên sử dụng không đồng bộ, hoãn lại hay bình thường? Thực thi JavaScript? Như thường lệ, điều này tùy thuộc vào tình huống và có một số câu hỏi có thể giúp bạn đưa ra quyết định đúng đắn.

Phần tử nằm ở đâu?

Việc thực thi không đồng bộ và lười biếng là quan trọng nhất khi phần tử không nằm ở cuối tài liệu. Các tài liệu HTML được phân tích theo thứ tự từ mở đến đóng. Nếu tệp JavaScript bên ngoài được đặt ngay trước thẻ đóng thì việc sử dụng async và defer sẽ ít thích hợp hơn vì lúc đó trình phân tích cú pháp sẽ phân tích hầu hết tài liệu và các tệp JavaScript sẽ không còn ảnh hưởng đến nó nữa.

Kịch bản có tự cung cấp được không?

Đối với các tệp không phụ thuộc vào các tệp khác và/hoặc không có bất kỳ phần phụ thuộc nào, thuộc tính async sẽ hữu ích nhất. Vì chúng ta không quan tâm đến thời điểm tệp được thực thi nên tải không đồng bộ là tùy chọn phù hợp nhất.

Tập lệnh có dựa trên DOM được phân tích cú pháp đầy đủ không?

Trong nhiều trường hợp, tệp tập lệnh chứa các hàm tương tác với DOM. Hoặc có lẽ có sự phụ thuộc vào một tệp khác trên trang. Trong những trường hợp như vậy, DOM phải được phân tích cú pháp hoàn toàn trước khi tập lệnh được thực thi. Thông thường, một tệp như vậy được đặt ở cuối trang để đảm bảo rằng mọi thứ đã được phân tích cú pháp để nó hoạt động. Tuy nhiên, trong trường hợp vì lý do nào đó mà tệp phải được đặt ở một vị trí khác, thuộc tính defer có thể hữu ích.

Kịch bản nhỏ và phụ thuộc?

Cuối cùng, nếu tập lệnh tương đối nhỏ và/hoặc phụ thuộc vào các tệp khác thì có thể cần xác định nội tuyến. Mặc dù mã nội tuyến chặn việc phân tích cú pháp tài liệu HTML nhưng sẽ không có vấn đề gì lớn nếu tài liệu có kích thước nhỏ. Ngoài ra, nếu nó phụ thuộc vào các tệp khác, có thể cần một số khóa nhỏ.

Hỗ trợ và công cụ trình duyệt hiện đại

Hỗ trợ cho các thuộc tính async và defer rất phổ biến:




Cần lưu ý rằng hoạt động của các thuộc tính này có thể hơi khác nhau giữa các công cụ JavaScript. Ví dụ: trong V8 (được sử dụng trong Chrome), một nỗ lực được thực hiện để phân tích cú pháp tất cả các tập lệnh, bất kể thuộc tính của chúng, thành một luồng chuyên dụng riêng biệt để thực thi tập lệnh. Do đó, tính chất "chặn trình phân tích cú pháp" của các tệp JavaScript phải được giảm thiểu theo mặc định.

Đôi khi cần phải tải dữ liệu không đồng bộ từng bước. Và nó có thể là bất cứ điều gì. Bắt đầu từ việc tải các thư mục phụ thuộc (ví dụ: quốc gia -> thành phố), kết thúc bằng việc kết hợp và xử lý thông tin với có nhiều nguồn(ví dụ: bạn đang sử dụng một số dịch vụ khác nhau, và mỗi người trong số họ dành thời điểm khác nhauđể tạo dữ liệu).

Và bây giờ đơn giản hơn một chút.

Sự cố khi tải dữ liệu không đồng bộ từng bước trong jQuery (ajax)

Nếu bạn cần kết nối một số yêu cầu ajax được thực hiện tuần tự trong jQuery thì hầu hết giải pháp đơn giản will - thực hiện cuộc gọi đến hàm sau vào cuối mỗi trình xử lý thành công. Điều này không chỉ khá đơn giản mà còn không gây ra bất kỳ vấn đề gì. Ví dụ,

// Yêu cầu đầu tiên $.ajax(url, ( ... thành công: function (kết quả) ( // Một số mã... // Gọi trình xử lý tiếp theo nextLoader(); ) ));

Và bây giờ, giả sử, trước mặt bạn đứng thêm một chút nhiệm vụ khó khăn. Ví dụ: bạn chỉ cần chạy một chức năng sau khi một số yêu cầu không đồng bộ đã hoàn thành (ví dụ: nhận bong bóng cho một trang web). Tất nhiên, chúng cũng có thể được kết nối thành một chuỗi thẳng, như hình trên. Tuy nhiên, cùng lúc đó, bản chất của sự không đồng bộ bắt đầu bị mất đi. Và cũng có thể bạn đang xây dựng sự phụ thuộc giữa các khối hoàn toàn không liên quan. Đồng ý rằng chỉ báo TCI và dữ liệu whois không hoàn toàn phụ thuộc vào nhau.

Tuy nhiên, bất chấp mọi sự tinh tế, một vấn đề như vậy có thể được giải quyết khá nhanh chóng, mặc dù hơi vụng về.

Nhưng bạn sẽ làm gì nếu nhiệm vụ của bạn trở nên khó khăn hơn? Khi bạn cần phân phối tất cả các hoạt động và tải dữ liệu thành các giai đoạn. Ví dụ: bạn đang tạo một mẫu hội thoại. Giai đoạn đầu tiên sẽ liên quan đến việc lấy dữ liệu cho tất cả các trường (danh sách thả xuống, nhóm hộp kiểm, v.v.). Ở giai đoạn thứ hai, trình xử lý cho các trường đã tạo sẽ được xác định. Và ở giai đoạn thứ ba, sau khi “mọi thứ và mọi thứ” đã được tải đầy đủ, hãy mở quyền truy cập vào các nút khác nhau và các thành phần giao diện khác (để những bàn tay vui tươi không tạo ra nhiều vấn đề cho bạn). Về mặt trực quan, nó có thể trông như thế này:

Đồng ý rằng việc tổ chức các cuộc gọi của tất cả các chức năng trong một chuỗi không những không phải là một nhiệm vụ dễ dàng mà còn không mấy dễ chịu. Ngoài ra, hãy tưởng tượng rằng bạn cần thêm một số trường và các trình xử lý khác nhau. Chuyện gì sẽ xảy ra? Đầu của bạn sẽ bắt đầu sôi sục khi tìm kiếm đúng chỗ “chèn vào đâu”. Ở đây bạn đã cần một số loại cơ chế cho phép bạn sắp xếp tất cả các lần phóng theo từng giai đoạn.

Chúng tôi đang viết một tập lệnh để tổ chức tải không đồng bộ từng bước trong jQuery

Bước đầu tiên là quyết định câu hỏi hoàn toàn hợp lý "tại sao không sử dụng các thư viện làm sẵn?" Như vậy, không có câu trả lời cho câu hỏi này. Mọi thứ phụ thuộc rất nhiều vào nhiệm vụ. Vì từ "thư viện" thường có nghĩa là:

  • thiếu khả năng kiểm soát mã (bạn không thể thay đổi logic bên trong của thư viện; và nếu bạn làm điều này, thì mọi thay đổi có thể quay trở lại ám ảnh bạn trong tương lai)
  • sự cần thiết phải nghiên cứu nó Các tính chất cơ bản và các nguyên tắc (thông thường điều này phụ thuộc vào việc đọc tất cả các tài liệu có thể có và một loạt các bài kiểm tra khác nhau)
  • Hạn chế về phiên bản jQuery(nếu sử dụng các cơ chế hạt nhân phức tạp thì có thể liên kết với phiên bản của thư viện jQuery)
  • các vấn đề tương thích có thể xảy ra với các tập lệnh khác (không chắc chắn rằng thư viện sẽ hoạt động chính xác với các thư viện khác)
  • sự phong phú quá mức của chức năng và kết quả là sự hiện diện của “các hạn chế bổ sung”
  • vân vân.

Lưu ý: Đừng để bị lừa, vì các thư viện có số lượng lớnưu. Nếu bạn còn nhớ, jQuery cũng là thư viện tương tự. Bài viết tập trung vào những rủi ro và thời gian đầu tư bổ sung mà bạn có thể cần.

Đó là lý do tại sao trước tiên bạn phải quyết định về nhiệm vụ của mình (số lượng, tần suất xảy ra), thời gian (bạn sẵn sàng chi bao nhiêu để giải quyết vấn đề), bạn sẵn sàng hy sinh điều gì (là khả năng nhanh chóng sửa chữa điều gì đó quan trọng đối với bạn). ; kích thước của thư viện có quan trọng không; bao nhiêu? hạn chế phù hợp với bạn), sở thích (ví dụ: về cơ bản bạn không sử dụng thư viện). Và chỉ sau khi bạn trả lời những câu hỏi này, hãy cố gắng trả lời câu hỏi “tại sao việc sử dụng các thư viện làm sẵn lại đáng hoặc không đáng?”

Nếu bạn tự trả lời rằng bạn muốn sử dụng thư viện, thì, như một tùy chọn, bạn có thể tải xuống một ví dụ thử nghiệm làm sẵn với tập lệnh tạo sẵn ở cuối bài viết.

Nếu bạn tràn đầy nhiệt huyết và quyết tâm thì chúng ta sẽ tiến hành những hành động tiếp theo.

Biên soạn yêu cầu cho kịch bản

Trước khi thực hiện bất cứ việc gì cũng cần đưa ra những yêu cầu nhỏ để không bị lạc đề trong quá trình thực hiện. Điều này dẫn đến một danh sách như thế này:

  • Việc kết nối và thiết lập tập lệnh sẽ diễn ra tự động (bạn chỉ cần kết nối tệp js)
  • Kết nối lại tệp tập lệnh sẽ không gây ra sự cố
  • Chỉ sử dụng các cơ chế jQuery tiêu chuẩn
  • Giao diện phải đơn giản và dễ hiểu
  • Bạn có thể tạo một số chuỗi giai đoạn độc lập
  • Bạn phải luôn có thể nhanh chóng điều chỉnh các hành động của tập lệnh
  • Tập lệnh không được áp đặt các hạn chế phức tạp đối với mã của bạn (tối đa - cần thêm chức năng thông báo về việc thực thi mã)

Lưu ý: Luôn xây dựng các yêu cầu để trong quá trình triển khai, bạn không bắt đầu làm điều gì đó không bắt buộc. Và hãy chắc chắn bao gồm những điểm “rất rõ ràng” trong đó, để những điểm này tiếp tục “rất rõ ràng”.

Lập dự án thử nghiệm

Cấu trúc dự án sẽ trông như thế này:

  • css - thư mục có kiểu
  • hình ảnh - danh mục có hình ảnh (để tạo hiệu ứng hình ảnh)
    • ajax-loader.gif - tải hình ảnh
  • js - thư mục chứa tập lệnh
    • jquery-ajax-stage.js - tập lệnh để tải theo giai đoạn
  • data.json - dữ liệu thử nghiệm
  • index.html - trang chủ

Lưu ý: Khi tạo cấu trúc của dự án thử nghiệm, hãy cố gắng làm cho nó gần nhất có thể với cấu trúc của dự án thực. Điều này sẽ giúp bạn nắm bắt được các vấn đề liên quan đến cấu trúc trong quá trình phát triển.

Tệp có dữ liệu thử nghiệm - data.json

Tệp này chỉ cần thiết để đảm bảo rằng việc tải dữ liệu qua ajax sẽ không ảnh hưởng gì. Bạn có thể điền nó bằng bất kỳ json nào. Ví dụ như thế này:

( dữ liệu: "Rất nhiều dữ liệu")

Lưu ý: Cố gắng làm cho các trường hợp thử nghiệm giống nhất có thể với trường hợp thực tế. Ngay cả khi các lệnh gọi hàm là vô nghĩa.

Tệp kiểu - template.css

Tập tin này chỉ cần thiết để hiển thị tất cả các kiểu riêng biệt. Vì phong cách không liên quan gì đến sự phát triển của kịch bản. Có, và nó chỉ được coi là cách thực hành tốt. Bản thân các phong cách:

Bảng bên trái ( float: left; đệm-phải: 10px; ) .bảng bên phải ( float: left; đệm-phải: 10px; ) table.table-loader ( border-spacing: 0px; border-collapse: thu gọn; chiều rộng : 300px; ) table.table-loader tr td ( đệm: 5px; viền: 1px rắn #ccc; )

Tệp tập lệnh để tải không đồng bộ theo giai đoạn - jquery-ajax-stage.js

Việc thực hiện tải không đồng bộ từng bước.

(function (parentObject) ( // Bảo vệ chống lại việc định nghĩa lại if(parentObject.eventManager) return; // Xác định đối tượng parentObject.eventManager = ( // Thêm một giai đoạn addStage: function (el, stageName) ( var elCount = $( el).length; // Kiểm tra tính chính xác của các tham số if(elCount > 0 && !!stageName) ( // Một giai đoạn như vậy đã tồn tại if (($(el).get(0).eventStages = $(el) .get(0).eventStages || ())) return; // Xác định "nfg $(el).get(0).eventStages = ( WaiterCount: 0, // Bộ đếm các đối tượng trong trạng thái chờ dữ liệu onEvent: / / TRONG mảng này tất cả các chức năng được gọi sẽ được lưu trữ); ) ), // Xóa giai đoạn RemoveStage: function (el, stageName) ( var elCount = $(el).length; // Kiểm tra tính chính xác của các tham số if(elCount > 0 && !!stageName) ( // Như vậy giai đoạn được tìm thấy nếu (( $(el).get(0).eventStages = $(el).get(0).eventStages || ())) ( delete ($(el).get(0).eventStages = $(el).get (0).eventStages || ()); ($(el).get(0).eventStages = $(el).get(0).eventStages || ()) = null; ) ) ), // Tăng bộ đếm của các hàm được thực thi cho giai đoạn addStageWaiter: function (el, stageName) ( var elCount = $(el).length, stage = ($(el).get(0).eventStages = $(el) ).get(0).eventStages || ()); // Kiểm tra tính chính xác của các tham số if(elCount > 0 && !!stageName && stage) ( // Tăng bộ đếm tải stage.waiterCount++; ) ), // Giảm bộ đếm của các hàm được thực thi cho giai đoạn // Tức là. thông báo rằng hàm đã được thực thi RemoveStageWaiter: function (el, stageName) ( var elCount = $(el).length, stage = ($(el).get(0).eventStages = $(el).get(0) .eventStages || ()); // Kiểm tra tính đúng đắn của các tham số if(elCount > 0 && !!stageName && stage) ( // Giảm bộ đếm tải stage.waiterCount--; // Kiểm tra trạng thái của giai đoạn này .checkStage(el, stageName); ) ), // Kiểm tra trạng thái của giai đoạn checkStage: function (el, stageName) ( var elCount = $(el).length, stage = ($(el).get(0) .eventStages = $(el).get(0) .eventStages || ()); // Kiểm tra tính chính xác của các tham số if(elCount > 0 && !!stageName && stage) ( if (stage.waiterCount 0) ( / / Hàng đợi FIFO - vào trước, ra trước, như trong kho giai đoạn. onEvent.shift())(; ) ) ) ), // Thêm lệnh gọi hàm sẽ chạy khi toàn bộ giai đoạn onLoadStage được thực thi: function (el, stageName, funcHandler) ( var elCount = $(el).length, stage = ($ (el).get(0).eventStages = $(el).get(0).eventStages || ()); // Kiểm tra các tham số đều đúng if(elCount > 0 && !!stageName && stage && typeof (funcHandler) = == "function") ( // Thêm trình xử lý stage.onEvent.push(funcHandler); // Kiểm tra trạng thái của stage this.checkStage(el, stageName); ) ) ); ))(cửa sổ);

Trang thử nghiệm - index.html

Trang thử nghiệm khá lớn (khoảng 160 dòng), vì vậy chỉ một phần mã sẽ được cung cấp. Phiên bản đầy đủ bạn luôn có thể tìm thấy tệp trong kho lưu trữ zip.

Chúng tôi bao gồm tất cả các tập tin cần thiết:

Hãy tạo một vài khối thử nghiệm. Khối bao gồm nút khởi chạy và bảng nơi dữ liệu sẽ được ghi lại từng bước.

Bắt đầu tải xuống

Hãy xác định một hàm sẽ tạo các hàm kiểm tra cho các giai đoạn:

function getFakeLoader(storage, currStage, startDate, selector) ( return function () ( setTimeout(function () ( $.ajax("data.json?callback=?", ( contentType: "text/plain; charset=utf-8 ", dataType: "jsonp", jsonpCallback: function (kết quả) ( $(selector).html("Thời gian từ khi bắt đầu: " + ((+new Date() - startDate)/1000.0).toFixed(2) + " giây "); // Viết thời gian tải window.eventManager.removeStageWaiter(storage, currStage); // Giảm bộ đếm ) )); ), Math.random() * (3000) + 1000 // Delay từ 1 đến 4 giây ); ); )

Chúng tôi tạo một hàm mô tả logic cho từng khối kiểm tra:

function formTestFor(selector) ( $(selector + " .start-process").click(function () ( var startDate = new Date(); // Để đẹp hơn, hãy thêm ảnh setLoaderImgs(selector); // Xác định cửa sổ giai đoạn .eventManager .addStage($(selector + " .table-loader"), "1"); window.eventManager.addStage($(selector + " .table-loader"), "2"); window.eventManager.addStage ($ (selector + " .table-loader"), "3"); // Chặn nút cho đến hết giai đoạn $(selector + " .start-process").attr("disabled", "disabled" ); // Lấp đầy hàng đợi chờ 3 lần tải cho mỗi giai đoạn // Trên thực tế, những hành động này sẽ xảy ra ở những nơi mà các chức năng của giai đoạn được khởi chạy window.eventManager.addStageWaiter($(selector + " .table-loader"), "1 "); ... window.eventManager.addStageWaiter ($(selector + " .table-loader"), "3"); // Bây giờ hãy tạo trong thứ tự ngược lại(để rõ ràng) tải hàm // Trên thực tế, những hành động này sẽ xảy ra ở những nơi hàm được xác định window.eventManager.onLoadStage($(selector + " .table-loader"), "2", getFakeLoader($(selector + " .table-loader"), "3", startDate, selector + " .row-3 .td-1")); ... window.eventManager.onLoadStage($(selector + " .table-loader"), "1", getFakeLoader($(selector + " .table-loader"), "2", startDate, selector + " .row -2 .td-3")); // Thêm một đầu ra văn bản thông thường của các giai đoạn đã hoàn thành window.eventManager.onLoadStage($(selector + " .table-loader"), "1", function () ( $(selector + " .row-1-end td" .html ("Giai đoạn đầu tiên kết thúc sau " + ((+new Date() - startDate)/1000.0).toFixed(2) + " giây. Giai đoạn tiếp theo bắt đầu."); )); ... window.eventManager.onLoadStage($(selector + " .table-loader"), "3", function () ( $(selector + " .row-3-end td").html("Giai đoạn thứ ba đã kết thúc trong " + ((+new Date() - startDate)/1000.0).toFixed(2) + " giây.
Quá trình tải hoàn tất"); )); // Sau khi hoàn thành giai đoạn thứ ba, hãy mở khóa nút onLoadStage window.eventManager.onLoadStage($(selector + " .table-loader"), "3", function () ( // Mở khóa nút $(selector + " .start-process").attr("disabled", null); )); // Bây giờ hãy chạy các chức năng của giai đoạn đầu tiên getFakeLoader($(selector + " .table-loader") , "1", startDate, bộ chọn + " .row-1 .td-1")(); getFakeLoader($(selector + " .table-loader"), "1", startDate, bộ chọn + " .row-1 .td-2")()); getFakeLoader($(selector + " .table-loader"), "1", startDate, selector + " .row-1 .td-3")(); // Quan sát.. . )); )

Bây giờ chúng tôi thu thập tất cả các tệp vào dự án và chuyển sang thử nghiệm và trình diễn ban đầu.

Hãy xem kết quả

Mở tệp index.html trong trình duyệt. Giao diện sau sẽ được hiển thị:

Như bạn có thể thấy, chúng tôi có sẵn hai nút để khởi chạy các quy trình song song. Sau khi nhấp vào chúng, quá trình tải xuống các khối tương ứng sẽ bắt đầu. Và nó sẽ trông giống như thế này:

Sau khi cả hai quá trình đã hoàn tất quá trình thực thi, hãy xem thời gian và đảm bảo rằng các giai đoạn diễn ra theo đúng thứ tự:

Sau khi hoàn thành thử nghiệm ban đầu, chúng tôi chuyển sang kiểm tra các yêu cầu:

  • Việc kết nối và thiết lập tập lệnh sẽ diễn ra tự động (bạn chỉ cần kết nối tệp js) - Có
  • Việc kết nối lại tệp tập lệnh sẽ không gây ra sự cố - Có
  • Chỉ sử dụng các cơ chế jQuery tiêu chuẩn - Có (chỉ sử dụng chức năng bộ chọn)
  • Giao diện phải đơn giản và dễ hiểu - Có
  • Bạn có thể tạo một số chuỗi giai đoạn độc lập - Có
  • Bạn luôn có thể nhanh chóng sửa các hành động của tập lệnh - Có (tập lệnh được viết khá đơn giản; phần chính bao gồm kiểm tra dữ liệu đầu vào)
  • Tập lệnh không được áp đặt các hạn chế phức tạp đối với mã của bạn (tối đa - cần thêm chức năng để thông báo về việc hoàn thành của nó) - Có (bên trong các hàm getFakeLoader, chỉ có chức năng thông báo về việc hoàn thành của nó được gọi)

Giờ đây, bạn đã có một tập lệnh đơn giản và rõ ràng giúp bạn nhanh chóng sắp xếp việc thực thi các chức năng theo từng bước, có thể là tải dữ liệu hoặc đơn giản là thực hiện các thao tác.