JavaScript’im tarayıcınızı neredeyse nasıl yok etti ve nasıl düzeltirim
İlk olarak, biraz arka plan. Yeni UI WP’nin DB Pro’yu geçtiğini görmüş olabilirsiniz, ancak kodu okumamış olabilirsiniz. Bunu size açıklamayacağım, ama ilgilenenler için bu, üzerinde çalışmaya ilk başladığımda Codepen’de yaptığım “eskiz” in başlangıcı: Kalemin omurgasını Jrgould (@jrgould) içinde görün Codepen. UI Geçişin ilerlemesi bir model ve omurga ekranı kullanılarak yapılır. Her ilerleme görünüm ve model ile temsil edilir. Geçişteki her “aşama” (rezervler, göç, medya), tüm bireysel ilerleme bıçaklarını içeren ve yöneten omurga görünümü ve modeli ile de temsil edilir. Son olarak, genel göç, aşamaları içeren ve yöneten tek bir omurga ekran ve model ile temsil edilir. Gerçekten geçiş yapmak için omurgayı kullanmıyoruz, bu nedenle model daha çok bir ekran modeli gibi ele alınıyor ve omurganın yönlendirici modülü veya senkronizasyon gibi uygulamalara daha fazla odaklanan herhangi bir koleksiyonunu veya özelliğini kullanmıyoruz.
Yeni kullanıcı arayüzü, taşındığımız her medya dosyası için bir mini görüntü içeren ilerleme çubuğunu gösterir, bu nedenle 10 bin medya dosyası ile 30-50 bin ilerleme bıçağı anlamına gelir.Düşünme kesinlikle çok fazla bellek kullanıyor ve her şeyi yavaşlatıyor, kodun içine dalıyorum ve görünümüm ilerleme çubuğunu nasıl gösteriyor, böylece DOM’a herhangi bir zamanda sadece birkaç yüz düğüm eklenecek, geri kalanı DOM’dan silinecek ve sorulabilmesi için gizli.Şaşırdım ve endişeliydim, bu pek yardımcı olmadı.Bir sonraki adım omurganın kendisini suçlamaktır.WordPress yöneticisine dahil olduğu için kullanıyorum, ancak eski ve aptal olabilir ve geriatrikin aptallığı nedeniyle çok fazla bellek kullanabilir.
Bu yüzden omurgayı yeniden yazıyorum. Tamam, belki omurgayı yeniden yazmadım. Ancak modelimin ve omurga ekranımın uygulanması için bir yedek yazdım – bu da onu bir nesneye sardı. Bu yeni model prototipi, SET, GET, AÇIK, OFF ve Tetikleyici gibi çeşitli temel yöntemleri içeren model ve omurga ekranını genişletmek için yazdığım birkaç kodu yeniden kullanmamı sağlıyor: MyModel = Function (UserProps) { var ret = {öznitelikler: {}, olaylar: {}, get: function (prop) {return this.attributes [prop]; }, set: function (prop, val) {this.tigger (‘değiştir’, pervane, this.atttribes [prop], val); this.Tigger (‘değiştir:’ + pervane, pervane, this.atttribes [prop], val); this.atttribes [prop] = val; }, on: function (olay, geri arama) {if (! this.events [olay]) {this.events [event] = []; } this.eval [olay]. push (geri arama)}, kapalı: function (olay, geri arama) {if (! this.events [olay]) {return} var geri çağırma = this.events [olay]; if (‘function’ === typeof geri arama) {var index = callacksof (geri arama); if (-1! == index) {callbacks.splice (dizin, 1); Bu. dönüş; }} else {this.events [event] = [] return; }}, tetik: function (olay) {var self = this; var args = array.pototype.slice.apply (bağımsız değişkenler, [1]); if (this.events [olay] && this.events [olay]. Uzunluk) {var eventCallbacks = this.events [event] .slice (); while (eventCallbacks.Length) {var ev = eventCallbacks.shift (); Ev.Apply (benlik, args); }}},}; if (‘object’ === UserProps) {_.each (userProps, işlev (prop, dizin) {ret [index] = prop;}, this); } Return ret; };
Ayrıca başarısız oldu. Bu aslında model ve omurga ekranını kullanırken daha yavaş çalışıyor gibi görünüyor, bu yüzden fikri sildim ve suçluyu aramaya devam ettim. Bu çöp çünkü render olan Dom düğümlerinin sayısının büyük bir etkisi yok ve Omurga hafızanın kullanımını şişiriyor gibi görünüyor, JavaScript’te hafıza sızıntısına neyin neden olduğuna dair araştırma yapmaya başladım. Benden daha akıllı olan geliştiriciler tarafından yazılmış ve çöp koleksiyonu denilen bir şey hakkında biraz bilgi edinen bir dizi makaleyi okudum. Chrome V8 gibi modern JavaScript makineleri çok optimize edilmiş ve selefinden daha fazlasını idare edebilir (hepimiz çılgın parçacıkların bir gösterisi gördük). Kullandıkları hilelerden birine, bu çok yeni olmasa da, bir noktada kullanılan ancak artık kullanılmayan değişkenler ve işlevlerden mümkün olduğunca fazla bellek serbest bırakmaya çalışan bir JS motor özelliği olan çöp koleksiyonu denir. .
Peki omurga ile ilişki nedir? Geri arama, ana nesnenin atık toplamasını önler. Bunun nedeni, arka çağrı üst nesnenin dışında çağrılsa da, hala bağlamı korur. Aşağıdakileri düşünün: var myView = ockbone.view.extend ({init: function () {this.model.on (‘değiştir’, this.render, this);}, render: function () { /* görünümü oluşturur */}}); Ekran başlatıldıktan sonra, Değişim Modeli etkinliğine bir geri çağrı kaydetti, tüm nesneler çöp toplamadan geri çağrıların toplanabileceği modellere çıkarıldı. Çoğu durumda, bu iyidir, ancak 50.000 modele bağlı 50.000 ekranınız varsa, hepsi sahne modeline bağlıdır? Bu bazı sorunlara neden olacaktır … JavaScript: Pratik parçalar, kendi görünüşünün model ve nesnesi tarafından temsil edilen her ilerlemeyi sağlamak çok hoştur. Bu, UI geçiş ilerlemesinin her bileşeninin kendini düzenlemesine izin verirken, diğerleri daha düşük seviyeli bileşenlerde yapılan değişikliklere uygun şekilde tepki verecektir. Bu nesnelerin kaldırılması, model ve sahne görünümünün artık her modelin sorumluluklarını ve ilerleme çubuğunun görüntülenmesi gerektiği anlamına gelir. JavaScript’ten herhangi bir yöntem içermeyen 50.000 basit nesneyi ele almasını istemek çok fazla olmamalı, ancak nesnedeki değişiklikleri nasıl izliyorsunuz?
JS’de, diziler veya nesneler gibi nesneler içeren herhangi bir değişkenin değerlerden ziyade referanslarla aktarıldığını biliyor muydunuz? İşte bir örnek: Function Changethings (var1, var2) {var1 = 12 * 2; var2.foo = ‘değiştirildi’; var2 = ”; Console.log (VAR1, VAR2); } işlev logthings (var1, var2) {console.log (var1, var2); } Var myval = 12; Var myobj = {foo: ‘bar’, baz: ‘bing’} logthings (myval, myobj); // 12, object {foo: “bar”, Baz: “Bing”} Changethings (myval, myobj); // 24, “” logthings (myval, myobj); // 12, Object {foo: “Değiştir”, Baz: “Bing”} Bu, büyük bellek maliyetleri olmayan çok iyi şeyler yapmamızı sağlar. Refactor’um ilerleme çubuğu nesneleri içeren bir dizi ile bittikten sonra şuna benzer: [{name: ‘image001.jpg’, boyut: 1024, aktarılan: 0}, {name: ‘image002.jpg’, boyut: 1288 , Aktarılan: 0}, …] Ayrıca, dizideki adlara dayalı nesnelere, dizi işlevselliği ödemeden isimlere dayalı olarak erişmemi sağlayan bir “arama” nesnemiz var: {‘image001.jpg’: 0, ‘image002.jpg ‘1, …} Şimdi, JavaScript’in modelimizin nesnenin durumunu izleme şeklini basitleştirmek için referanslarla nesnelerden geçtiği gerçeğinden yararlanabiliriz. Örneğin, bu, sahne modeline ilerleme eklemek için bir ekrandır:
addItem: function (itemobj) {var item = _.clone (itemobj);// ref’i orijinal obj this.get (‘öğeler’). push (öğe);this.get (‘Itemslookup’) [item.name] = this.get (‘öğeler’). Uzunluk – 1;this.Tigger (‘öğe: eklendi’, öğe);} Öğe AddItem yöntemine (VAR anahtar kelimesi sayesinde) kapsanmış olsa da, doğrudan öğeye bağlanan herhangi bir çağrıya devam edebiliriz: eklenir çünkü öğe gerçekten sadece klonlama nesnesine işaretçi tutar.Bu, bu etkinliğe yalnızca okuma nesnelerine erişmekle kalmayıp, tüm öğeler dizilerini almak veya dizideki öğelere erişmek için nesne öğelerini kullanmak zorunda kalmadan doğrudan değiştirebilirler.Bu, gerçek DOM öğesini yapmak gibi bir ekranda bir şeyler yapmak için çok kullanışlıdır:
// stageView.init () {… this.model.on (‘item: eklenti’, işlev (öğe) {if (! item. $ el) {öğe. $ el = $ (‘
‘ ) .Addclass (‘ProgressBar’) .css (‘genişlik’, item.transfered / item.size + ‘%’);}}, bu); JavaScript’teki nesne işaretçisinin bir başka ilginç yönü, bir nesnenin bir dizi başka nesne tarafından yerleştirilebilmesidir. Bu, nasıl filtreleyeceği veya sıralayacağınız konusunda birçok şey yapmaya gerek kalmadan şeyleri izlemek için kullanışlıdır. Örneğin, ilerleme bitmiş olarak işaretlendiğinde, DOM’dan öğeleri siler ve daha sonra göstermemiz gerekirse koruyucu olmak için sıraya koyacağız. Böyle bir şey böyle bir şekilde ulaşılır: // stageView.init () {… this.model.on (‘item: complete’, function (öğe) {item. $ El.remove (); this.itemqueue. push (öğe. $ el); if (100> this. $ el.find (‘.progressBar’). ;}}, bu); Burada Dom, “görünür” bir öğe kuyruğu “gibi davranıyor