javascript - Maksimum çağrı yığını boyutu aşıldı hatası


Bir Direct Web Remoting (DWR) JavaScript kütüphane dosyası kullanıyorum ve sadece Safari'de (masaüstü ve iPad) bir hata alıyorum

Şöyle diyor

Maksimum çağrı yığını boyutu aşıldı.

Bu hata tam olarak ne anlama geliyor ve işlem tamamen duruyor mu?

Ayrıca Safari tarayıcısı için herhangi bir düzeltme (Aslında iPad Safari’de, şöyle diyor

JS:çalışma süresi zaman aşımını aştı

ki bunun aynı çağrı yığını sorunu olduğunu varsayıyorum)

Cevap #1

Bu, kodunuzda bir işlevi çağırdığınız ve bunun da başka bir işlevi çağırdığı ve böyle devam ettiği, ta ki çağrı yığını sınırına ulaşana kadar anlamına gelir.

Bu neredeyse her zaman, temel durumu karşılanmayan özyinelemeli bir fonksiyondan kaynaklanır.

Yığını görüntüleme

Bu kodu göz önünde bulundurun...

(function a() {
    a();
})();

İşte birkaç çağrıdan sonra yığın...

Gördüğünüz gibi, çağrı yığını bir limite ulaşana kadar büyür: tarayıcının sabitlenmiş yığın boyutu veya bellek tükenmesi.

Bunu düzeltmek için, özyinelemeli fonksiyonunuzun karşılanabilecek bir temel durumu olduğundan emin olun...

(function a(x) {
    // The following condition 
    // is the base case.
    if ( ! x) {
        return;
    }
    a(--x);
})(10);

Cevap #2

Benim durumumda, değerleri yerine giriş öğelerini gönderiyordum:

$.post( '',{ registerName: $('#registerName') } )

Bunun yerine:

$.post( '',{ registerName: $('#registerName').val() } )

Bu, Chrome sekmemi, sayfa yanıt vermez hale geldiğinde bana 'Bekle/Sonuçlandır' ileti kutusunu bile göstermeyecek kadar dondurdu...

Cevap #3

Bunu bazen yanlışlıkla aynı JavaScript dosyasını iki kez içe aktarır/gömerseniz alabilirsiniz, denetçi araçlarındaki kaynaklar sekmesinde kontrol etmeye değer.

Cevap #4

Kodunuzda bir yerde bir özyinelemeli döngü var (yani, sonunda kendini tekrar tekrar çağıran ve yığın dolana kadar devam eden bir fonksiyon).

Diğer tarayıcıların ya daha büyük yığınları vardır (bu yüzden onun yerine bir zaman aşımı alırsınız) ya da hatayı bir nedenle yutarlar (belki de yanlış yerleştirilmiş bir try-catch yüzünden).

Hata oluştuğunda çağrı yığınına bakmak için hata ayıklayıcıyı kullanın.

Cevap #5

Yığın taşmalarını tespit etmedeki sorun, bazen yığın izlemesinin geri sarılması ve gerçekte ne olduğunu görememenizdir.

Bunun için Chrome'un daha yeni hata ayıklama araçlarından bazılarını faydalı buldum.

Performans sekmesine tıklayın, Javascript örneklemelerinin etkin olduğundan emin olun ve şöyle bir şey elde edeceksiniz.

Taşmanın nerede olduğu burada oldukça belli! extendObject'e tıklarsanız, kodda tam satır numarasını gerçekten görebileceksiniz.

Ayrıca yararlı ya da yanıltıcı olabilecek zamanlamaları da görebilirsiniz.

Sorunu aslında bulamıyorsanız başka faydalı bir yöntem, sorunun olduğunu düşündüğünüz yerlere bolca console.log ifadesi koymaktır. Yukarıdaki önceki adım size bunda yardımcı olabilir.

Chrome'da aynı veriyi tekrar tekrar çıkarsanız, sorunun nerede olduğunu daha net göstererek bunu böyle görüntüler. Bu durumda yığın, nihayet çökmeye başlamadan önce 7152 çerçeveye ulaştı:

Cevap #6

Benim durumumda, büyük bir bayt dizisini bir string'e dönüştürüyordum, şu şekilde:

String.fromCharCode.apply(null, new Uint16Array(bytes))

bytes birkaç milyon giriş içeriyordu, bu da yığına sığamayacak kadar büyük.

Cevap #7

Bu ayrıca bir Maksimum çağrı yığını boyutu aşıldı hatasına da neden olabilir:

var items = [];
[].push.apply(items, new Array(1000000)); //Bad

Aynı şekilde:

items.push(...new Array(1000000)); //Bad

Mozilla Dokümanlarından:

Ama dikkat edin: apply'ı bu şekilde kullanmak, JavaScript motorunun argüman uzunluğu sınırını aşma riskini beraberinde getirir. Çok sayıda argümanla bir fonksiyon uygulamanın sonuçları (tenslerce binlerce argüman düşünün) motorlar arasında değişir (JavaScriptCore'un sabit kodlanmış 65536 argüman limiti vardır), çünkü limit (hatta aşırı büyük yığın davranışının doğası bile) belirtilmemiştir. Bazı motorlar bir istisna fırlatır. Daha zararlı olanı, diğerleri uygulanan fonksiyona gerçekten geçirilen argüman sayısını keyfi olarak sınırlar. Bu son durumu göstermek için: eğer böyle bir motorun dört argüman limiti olsaydı (gerçekteki limitler elbette çok daha yüksektir), yukarıdaki örneklerde 5, 6, 2, 3 argümanlarının apply'e geçtiği, tam dizinin geçmediği gibi olurdu.

O halde dene:

var items = [];
var newItems = new Array(1000000);
for(var i = 0; i < newItems.length; i++){
  items.push(newItems[i]);
}

İlgili makaleler