2013-06-25 36 views
168

Tôi đã sử dụng AngularJS trong một thời gian ngắn, và đã tìm thấy nhu cầu sử dụng $timeout mỗi lần một lúc (Dường như thường là để bắt đầu một plugin jQuery).

Gần đây, tôi đã cố gắng để hiểu rõ hơn và sâu hơn về chu kỳ tiêu hóa và tôi đã xem qua chức năng $evalAsync.

Có vẻ như chức năng đó tạo ra các kết quả tương tự như $timeout, chỉ bạn không cho nó chậm trễ. Mỗi lần tôi đã sử dụng $timeout nó đã được với một sự chậm trễ của 0, vì vậy bây giờ tôi tự hỏi nếu tôi nên đã sử dụng $evalAsync thay thế.

Có sự khác biệt cơ bản nào giữa hai loại này không? Những trường hợp nào bạn sẽ sử dụng một trong những khác? Tôi muốn có cảm giác tốt hơn khi sử dụng cái nào.

Trả lời

246

Gần đây tôi đã trả lời về cơ bản câu hỏi này ở đây: (. Đó là câu trả lời liên kết đến một số trao đổi github với Misko) https://stackoverflow.com/a/17239084/215945

Để tóm tắt:

  • nếu mã được xếp hàng đợi sử dụng $ evalAsync từ một chỉ thị, nó sẽ chạy sau DOM đã được thao tác bởi Angular, nhưng trước trình duyệt hiển thị
  • nếu mã được xếp hàng đợi sử dụng $ evalAsync từ một bộ điều khiển, nó nên chạy trước DOM đã được thao túng bởi góc (và trước khi trình duyệt render) - hiếm khi làm bạn muốn điều này
  • nếu mã được xếp hàng đợi sử dụng $ timeout, nó nên chạy sau DOM đã được thao túng bởi kiễu góc, và sau trình duyệt render (mà có thể gây ra chập chờn trong một số trường hợp)
+15

Cảm ơn bạn đã giải thích. Một điều tôi không chắc chắn tôi hiểu mặc dù. Tại sao nó tạo sự khác biệt nếu bạn đang gọi $ evalAsync từ một bộ điều khiển hoặc một chỉ thị? AsyncQueue không biết liệu nó đã được đăng ký từ một bộ điều khiển hay chỉ thị, nó chỉ xếp hàng nó lên trên phạm vi hiện tại. Liệu nó có liên quan gì khi các công cụ chạy trong bộ điều khiển và bộ điều khiển? Tôi chỉ muốn hiểu phần đó. – dnc253

+0

@ dnc253, tôi chưa xem mã Angular, vì vậy tôi không biết câu trả lời cho câu hỏi (tốt) của bạn. Hy vọng rằng một người khác có thể bình luận. –

+15

có "từ chỉ thị" có nghĩa là "từ chức năng liên kết của chỉ thị" không? Hoặc là đúng của hành vi khi thực hiện từ một trong hai liên kết hoặc phương pháp điều khiển của một chỉ thị? – SimplGy

52

Đối với những ứng dụng phức tạp xây dựng, lưu ý rằng có là một hiệu suất im hiệp ước về sự lựa chọn của bạn. Ngoài ra, tôi muốn hoàn thành Đánh dấu câu trả lời với các chi tiết kỹ thuật hơn:

  • $ timeout (callback) sẽ đợi cho dòng điện tiêu hóa chu kỳ được thực hiện (tức cập nhật góc tất cả các mô hình và DOM), sau đó nó sẽ thực hiện gọi lại của nó - có khả năng ảnh hưởng đến mô hình góc - sau đó khởi chạy một số đầy đủ $apply trên phạm vi $ gốc và tìm lại mọi thứ.

  • $ evalAsync (callback), mặt khác, sẽ bổ sung thêm các callback với dòng điện, hoặc bên cạnh, tiêu hóa chu kỳ. Điều đó có nghĩa là nếu bạn đang ở trong một chu kỳ tiêu hóa (ví dụ trong một hàm gọi là từ một số chỉ thị ng-click), điều này sẽ không chờ đợi bất cứ điều gì, mã sẽ được thực thi ngay lập tức. Nếu bạn đang trong một cuộc gọi không đồng bộ, ví dụ: setTimeout, chu kỳ thông báo mới ($apply) sẽ được kích hoạt.

Vì vậy, về mặt biểu diễn nó luôn luôn là tốt hơn để gọi $evalAsync, trừ khi nó quan trọng đối với bạn là quan điểm được cập nhật trước khi thực hiện mã của bạn, ví dụ nếu bạn cần acces vào một số Thuộc tính DOM như các yếu tố chiều rộng và tương tự.

Nếu bạn muốn biết thêm chi tiết về sự khác biệt giữa $ timeout, $ evalAsync, $ tiêu hóa, $ áp dụng, tôi mời các bạn đọc câu trả lời của tôi trên đó câu hỏi khác: https://stackoverflow.com/a/23102223/1501926

Ngoài ra hãy chắc chắn để đọc các documentation:

các $ evalAsync không đảm bảo như khi biểu thức sẽ được thực hiện, chỉ có vậy:

  • nó sẽ thực hiện sau khi các chức năng đó lên kế hoạch các evaluatio n (tốt nhất là trước khi dựng hình DOM).
  • ít nhất một chu kỳ tiêu hóa $ sẽ được thực hiện sau khi thực thi biểu thức.

Lưu ý: nếu hàm này được gọi ngoài chu kỳ $ digest, chu kỳ $ digest mới sẽ được lên lịch. Tuy nhiên, khuyến khích luôn gọi mã để thay đổi mô hình từ trong một cuộc gọi $ áp dụng. Điều đó bao gồm mã được đánh giá qua $ evalAsync.

+0

Bạn có thể giải thích tại sao $ timeout là cần thiết nếu tôi cần truy cập một số thuộc tính DOM . Hãy nói rằng nếu tôi có

Chức năng xem của ng-bind không cập nhật thuộc tính dom trong bộ nhớ, tôi hiểu nó sẽ không có cơ hội để vẽ lại khung nhìn cho đến khi thoát khỏi chu trình tiêu hóa. –

+2

@SridharChidurala vì DOM ("HTML") được cập nhật trong chu kỳ thông báo, bạn phải chờ cho đến khi nó được thực hiện trước khi bạn có thể đọc các mofifications. Tuy nhiên điều này không được Angular khuyến khích, bạn nên đọc 'x' từ phạm vi của bạn trực tiếp chứ không phải từ DOM, vì vậy bạn không phải chờ đợi bất cứ điều gì. Ngoài ra, bạn nên sử dụng 'ng-style' với css thay vì thuộc tính' width' đã lỗi thời. Nếu bạn cần thêm trợ giúp, vui lòng mở câu hỏi mới trên StackOverflow. – floribon