Ember RunLoop nedir ve nasıl çalışır?


96

Ember RunLoop'un nasıl çalıştığını ve neyin işe yaradığını anlamaya çalışıyorum. Belgelere baktım , ancak yine de onunla ilgili birçok sorum var. RunLoop'un nasıl çalıştığını daha iyi anlamakla ilgileniyorum, böylece daha sonra bir kodun yürütülmesini ertelemek zorunda kaldığımda, ad alanı içinde uygun yöntemi seçebilirim.

  • Ember RunLoop ne zaman başlar. Yönlendiriciye veya Görünümlere veya Denetleyicilere veya başka bir şeye bağlı mı?
  • yaklaşık olarak ne kadar sürer (Bunun birçok şeye sormak için oldukça saçma olduğunu ve bağımlı olduğunu biliyorum, ancak genel bir fikir arıyorum veya belki bir runloop'un alabileceği minimum veya maksimum süre varsa)
  • RunLoop her zaman yürütülüyor mu, yoksa sadece uygulamanın başından sonuna kadar bir süreyi mi gösteriyor ve bir süre çalışmayabilir.
  • Bir görünüm bir RunLoop içinden oluşturulursa, tüm içeriğinin döngü sona erdiğinde DOM'a gireceği garanti edilir mi?

Bunlar çok basit sorularsa beni affedin, bence bunları anlamak benim gibi noob'ların Ember'ı daha iyi kullanmasına yardımcı olacak.


5
Çalıştırma döngüsü hakkında harika belgeler yok. Bu hafta üzerinde kısa bir slayt sunumu oluşturmaya çalışacağım.
Luke Melia

2
@LukeMelia bu soru hala umutsuzca dikkatinize ihtiyaç duyuyor ve görünüşe göre diğer insanlar aynı bilgiyi arıyor. RunLoop hakkındaki görüşlerinizi paylaşma şansınız varsa harika olur.
Aras

Yanıtlar:


199

Güncelleme 10/9/2013: Çalıştırma döngüsünün bu etkileşimli görselleştirmesine göz atın: https://machty.s3.amazonaws.com/ember-run-loop-visual/index.html

Güncelleme 5/9/2013: Aşağıdaki tüm temel kavramlar hala güncel, ancak bu işlemle birlikte Ember Run Loop uygulaması, bazı çok küçük API farklılıkları ile backburner.js adlı ayrı bir kitaplığa ayrıldı .

Öncelikle şunları okuyun:

http://blog.sproutcore.com/the-run-loop-part-1/

http://blog.sproutcore.com/the-run-loop-part-2/

Ember için% 100 doğru değiller, ancak RunLoop'un arkasındaki temel kavramlar ve motivasyon hala genellikle Ember için geçerlidir; yalnızca bazı uygulama ayrıntıları farklılık gösterir. Ancak sorularınıza gelince:

Ember RunLoop ne zaman başlar. Yönlendiriciye veya Görünümlere veya Denetleyicilere veya başka bir şeye bağlı mı?

Tüm temel kullanıcı olayları (örn. Klavye olayları, fare olayları, vb.) Çalışma döngüsünü başlatacaktır. Bu, yakalanan (fare / klavye / zamanlayıcı / vb.) Olay tarafından bağlı özelliklerde yapılan her türlü değişikliğin, kontrolü sisteme geri döndürmeden önce Ember'in veri bağlama sistemi boyunca tamamen yayılmasını garanti eder. Böylece, farenizi hareket ettirmek, bir tuşa basmak, bir düğmeye tıklamak, vb. Hepsi çalışma döngüsünü başlatır.

yaklaşık olarak ne kadar sürer (Bunun birçok şeye sormak için oldukça saçma olduğunu ve bağımlı olduğunu biliyorum, ancak genel bir fikir arıyorum veya belki bir runloop'un alabileceği minimum veya maksimum süre varsa)

Hiçbir noktada RunLoop, tüm değişiklikleri sisteme yaymanın ne kadar zaman aldığını takip edemez ve maksimum zaman sınırına ulaştıktan sonra RunLoop'u durdurmaz; daha ziyade, RunLoop her zaman tamamlanana kadar çalışır ve süresi dolan tüm zamanlayıcılar çağrılana, bağlamalar yayılıncaya ve belki de bağları yayılıncaya kadar durmaz . Açıktır ki, tek bir olaydan ne kadar fazla değişiklik yapılması gerekiyorsa, RunLoop'un bitmesi o kadar uzun sürecektir. İşte RunLoop'un, çalışma döngüsü olmayan başka bir çerçeveye (Backbone) kıyasla ilerleyen değişikliklerle nasıl tıkanabileceğine dair (oldukça haksız) bir örnek: http://jsfiddle.net/jashkenas/CGSd5/. Hikayenin ahlaki: RunLoop, Ember'da yapmak isteyeceğiniz çoğu şey için gerçekten hızlıdır ve Ember'in gücünün çoğunun yattığı yerdir, ancak kendinizi Javascript ile saniyede 60 kare hızında 30 daireyi canlandırmak istediğinizde bulursanız, orada Ember's RunLoop'a güvenmekten daha iyi bir yol olabilir.

RunLoop her zaman yürütülüyor mu, yoksa sadece uygulamanın başından sonuna kadar bir süreyi mi gösteriyor ve bir süre çalışmayabilir.

Her zaman çalıştırılmaz - kontrolü bir noktada sisteme geri döndürmesi gerekir, yoksa uygulamanız askıda kalır - diyelim ki, a'ya sahip olan while(true)ve sonsuza kadar devam eden bir sunucudaki çalışma döngüsünden farklıdır. sunucu kapatma sinyali alır ... Ember RunLoop'ta böyle bir şey yoktur while(true), ancak yalnızca kullanıcı / zamanlayıcı olaylarına yanıt olarak döndürülür.

Bir görünüm bir RunLoop içinden oluşturulursa, tüm içeriğinin döngü sona erdiğinde DOM'a gireceği garanti edilir mi?

Bakalım bunu çözebilecek miyiz. SC'den Ember RunLoop'a en büyük değişikliklerden biri, invokeOnceve invokeLast(SproutCore'un RL'si hakkındaki ilk bağlantıdaki şemada gördüğünüz) arasında ileri geri döngü yapmak yerine , Ember size Bir çalıştırma döngüsünün seyri, eylemin hangi kuyruğa ait olduğunu belirterek (örneğin kaynaktan:) eylemleri (çalışma döngüsü sırasında çağrılacak işlevler Ember.run.scheduleOnce('render', bindView, 'rerender');) programlayabilirsiniz.

Eğer bakarsak run_loop.jskaynak kodunda, gördüğünüz Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];bir Kor uygulamasında tarayıcıda JavaScript ayıklayıcısını açıp değerlendirmek henüz eğer Ember.run.queuessen kuyruklar daha dolgun listesini almak,: ["sync", "actions", "render", "afterRender", "destroy", "timers"]. Ember, kod tabanını oldukça modüler tutar ve kodunuzun yanı sıra kendi kodunun kitaplığın ayrı bir bölümünde daha fazla kuyruk eklemesini mümkün kılar. Bu durumda, Ember Views kitaplığı , özellikle kuyruktan sonra ekler renderve afterRendersıralar actions. Bunun neden bir saniye içinde olabileceğini anlayacağım. İlk olarak, RunLoop algoritması:

RunLoop algoritması, yukarıdaki SC çalıştırma döngüsü makalelerinde açıklananla hemen hemen aynıdır:

  • Sen RunLoop arasında kod çalıştırmasına .begin()ve .end()sadece Ember içinde yerine sonunda kodunuzu çalıştırmak isteyeceksiniz Ember.runiçten arayacak olan beginve endsenin için. (Yalnızca Ember kod tabanındaki dahili çalıştırma döngüsü kodu hala kullanır beginve endbu nedenle sadece bağlı kalmalısınız Ember.run)
  • Sonra end()denir RunLoop sonra vitese başladı geçirilen kod yığın tarafından yapılan her değişikliği yaymak için Ember.runişlevi. Bu, ilişkili özelliklerin değerlerinin yayılmasını, görünüm değişikliklerinin DOM'da oluşturulmasını, vb. İçerir. Bu işlemlerin (bağlama, DOM öğelerini oluşturma, vb.) Gerçekleştirilme Ember.run.queuessırası, yukarıda açıklanan dizi tarafından belirlenir :
  • Çalıştırma döngüsü, olan ilk kuyrukta başlayacaktır sync. Kod synctarafından sıraya planlanan tüm eylemleri çalıştırır Ember.run. Bu eylemlerin kendileri de aynı Çalıştırma Döngüsü sırasında gerçekleştirilecek daha fazla eylem planlayabilir ve tüm kuyruklar temizlenene kadar her eylemi gerçekleştirmesini sağlamak Çalıştırma Döngüsüne bağlıdır. Bunu yapmanın yolu, her kuyruğun sonunda, Çalıştırma Döngüsü önceden temizlenmiş tüm kuyruklara bakacak ve herhangi bir yeni eylemin planlanıp programlanmadığını kontrol edecektir. Öyleyse, en erken sıranın başlangıcında, yerine getirilmemiş zamanlanmış eylemlerle başlamalı ve kuyruğu boşaltmalı, adımlarını izlemeye devam etmeli ve tüm kuyruklar tamamen boşalana kadar gerektiğinde baştan başlamalıdır.

Algoritmanın özü budur. Bağlı veriler bu şekilde uygulama aracılığıyla yayılır. Bir Çalıştırma Döngüsü tamamlandıktan sonra, tüm bağlı verilerin tamamen yayılmasını bekleyebilirsiniz. Peki, DOM öğeleri ne olacak?

Ember Views kitaplığı tarafından eklenenler de dahil olmak üzere kuyrukların sırası burada önemlidir. Bunu fark et renderve afterRendersonra gel syncve action. syncSıra ciltli verileri çoğaltılmasına yönelik tüm eylemleri içerir. ( actionbundan sonra Ember kaynağında yalnızca seyrek olarak kullanılır). Yukarıdaki algoritmaya bağlı olarak, RunLoop kuyruğa geldiğinde rendertüm veri bağlamalarının senkronizasyonu bitireceği garanti edilir . Bu tasarım gereğidir: DOM öğelerini oluşturma gibi pahalı bir görevi daha önce gerçekleştirmek istemezsiniz.Veri bağlamalarını senkronize etmek, çünkü bu muhtemelen DOM öğelerini güncellenmiş verilerle yeniden oluşturmayı gerektirecektir - açıkçası tüm RunLoop kuyruklarını boşaltmanın çok verimsiz ve hataya açık bir yolu. Böylece Ember, renderkuyruktaki DOM öğelerini oluşturmadan önce yapabileceği tüm veri bağlama işlerini akıllıca kullanır .

Son olarak, sorunuzu yanıtlamak için, evet, gerekli tüm DOM işlemelerinin Ember.runbitiş saatine kadar gerçekleşmiş olmasını bekleyebilirsiniz . İşte size gösterilecek bir jsFiddle: http://jsfiddle.net/machty/6p6XJ/328/

RunLoop hakkında bilinmesi gereken diğer şeyler

Gözlemciler ve Bağlamalar

Gözlemciler ve Bağlamaların, "izlenen" bir özellikteki değişikliklere yanıt verme gibi benzer işlevselliğe sahip olsalar da, bir Çalıştırma Döngüsü bağlamında tamamen farklı davrandıklarını unutmamak önemlidir. Bağlama yayılımı, gördüğümüz gibi, syncsonunda RunLoop tarafından yürütülecek şekilde kuyruğa programlanır . Öte yandan, gözlemciler, izlenen özellik değiştiğinde, ilk olarak bir RunLoop kuyruğuna programlanmasına gerek kalmadan hemen ateş ederler. Bir Gözlemci ve bir bağın tümü aynı özelliği "izlerse", gözlemci her zaman bağlanmanın güncellenmesinden% 100 önce çağrılacaktır.

scheduleOnce ve Ember.run.once

Ember'ın otomatik güncelleme şablonlarındaki en büyük verimlilik artışlarından biri, RunLoop sayesinde, birden fazla özdeş RunLoop eyleminin tek bir eylemde birleştirilebilmesi (eğer isterseniz "iptal edilmesi") gerçeğine dayanmaktadır. run_loop.jsİç kısımlara bakarsanız , bu davranışı kolaylaştıran işlevlerin ilgili işlevler olduğunu göreceksiniz scheduleOnceve Em.run.once. Aralarındaki fark, var olduklarını bilmek ve çalışma döngüsü sırasında çok fazla şişkin, israflı hesaplamayı önlemek için sıradaki yinelenen eylemleri nasıl atabilecekleri kadar önemli değildir.

Peki ya zamanlayıcılar?

'Zamanlayıcılar' yukarıda listelenen varsayılan kuyruklardan biri olsa da, Ember yalnızca RunLoop test durumlarında kuyruğa başvurur. Öyle görünüyor ki, SproutCore günlerinde, ateşlenecek son şey olan zamanlayıcılarla ilgili yukarıdaki makalelerden bazı açıklamalara dayanarak böyle bir kuyruk kullanılmış olacaktı. Ember'da timerssıra kullanılmaz. Bunun yerine, RunLoop, dahili olarak yönetilen bir setTimeoutolay ( invokeLaterTimersişleve bakın ) tarafından döndürülebilir ; bu, mevcut tüm zamanlayıcılar arasında döngü yapmak, süresi dolanların tümünü ateşlemek, gelecekteki en erken zamanlayıcıyı belirlemek ve bir dahilisetTimeoutSadece bu olay için, bu durum RunLoop'u patladığında tekrar döndürür. Bu yaklaşım, her bir zamanlayıcının setTimeout çağrısı yapıp kendini uyandırmasından daha etkilidir, çünkü bu durumda, yalnızca bir setTimeout çağrısının yapılması gerekir ve RunLoop, aynı anda kapanabilecek tüm farklı zamanlayıcıları ateşleyecek kadar akıllıdır. zaman.

İle Daha zıplamaölçer synckuyruğunda

Burada, çalışma döngüsündeki tüm kuyruklar boyunca bir döngünün ortasında bulunan çalışma döngüsünden bir parçacık var. syncKuyruk için özel duruma dikkat edin : çünkü syncverilerin her yönde yayıldığı, özellikle uçucu bir kuyruk, Ember.beginPropertyChanges()herhangi bir gözlemcinin ateşlenmesini önlemek için çağrılır ve ardından bir çağrı yapılır Ember.endPropertyChanges. Bu akıllıca: syncKuyruğu temizleme sırasında, bir nesnedeki bir özelliğin nihai değerine dayanmadan önce birden çok kez değişmesi tamamen olasıdır ve her değişiklik için hemen gözlemcileri kovarak kaynakları israf etmek istemezsiniz. .

if (queueName === 'sync') 
{
    log = Ember.LOG_BINDINGS;

    if (log) 
    {
        Ember.Logger.log('Begin: Flush Sync Queue');
    }

    Ember.beginPropertyChanges();
    Ember.tryFinally(tryable, Ember.endPropertyChanges);

    if (log) 
    { 
        Ember.Logger.log('End: Flush Sync Queue'); 
    }
} 
else 
{
   forEach.call(queue, iter);
}

Bu yardımcı olur umarım. Sadece bu şeyi yazmak için kesinlikle biraz öğrenmem gerekiyordu, bu da mesele buydu.


3
Harika yazı! "Gözlemcilerin anında ateş etmeleri" olayının bir noktada değişebileceği ve onları bağlama gibi geciktirebileceği söylentileri duyuyorum.
Jo Liss

@JoLiss evet, bunu birkaç aydır duymuş gibi hissediyorum ... ne zaman
ulaşıp ulaşmayacağından

1
Brendan Briggs, Ocak 2014 Ember.js NYC buluşmasında Run Loop hakkında harika bir sunum yaptı. Video burada: youtube.com/watch?v=iCZUKFNXA0k
Luke Melia

1
Bu cevap Ember Run Loop hakkında bulduğum en iyi kaynaktı, çok iyi iş! Yakın zamanda, çalışmanıza dayalı olarak Çalıştırma Döngüsü hakkında kapsamlı bir eğitim yayınladım ve bu mekanizmanın daha da ayrıntılarını açıklayacağını umuyorum. Mevcut burada on.netguru.co/ember-ebook-form
Kuba Niechciał
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.