Ukuran tumpukan panggilan maksimum melebihi kesalahan

533

Saya menggunakan file perpustakaan JavaScript Direct Web Remoting (DWR) dan saya mendapatkan kesalahan hanya di Safari (desktop dan iPad)

Ia mengatakan

Ukuran tumpukan panggilan maksimum terlampaui.

Apa sebenarnya arti kesalahan ini dan apakah itu berhenti memproses sepenuhnya?

Juga setiap perbaikan untuk Safaribrowser (Sebenarnya pada iPad Safari, katanya

JS: eksekusi melebihi batas waktu

yang saya asumsikan adalah masalah tumpukan panggilan yang sama)

testndtv
sumber
2
saya mendapatkan kesalahan ini ketika mencoba mengirim variabel (tanpa mendeklarasikannya), melalui datadi ajax. Memperbaiki kesalahan dengan mendeklarasikan variabel.
phpfresher

Jawaban:

621

Ini berarti bahwa di suatu tempat dalam kode Anda, Anda memanggil fungsi yang pada gilirannya memanggil fungsi lain dan seterusnya, sampai Anda mencapai batas tumpukan panggilan.

Ini hampir selalu karena fungsi rekursif dengan kasus dasar yang tidak terpenuhi.

Melihat tumpukan

Pertimbangkan kode ini ...

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

Berikut adalah tumpukan setelah beberapa panggilan ...

Inspektur Web

Seperti yang Anda lihat, tumpukan panggilan tumbuh hingga mencapai batas: ukuran hardcod browser atau kehabisan memori.

Untuk memperbaikinya, pastikan bahwa fungsi rekursif Anda memiliki kasus dasar yang dapat dipenuhi ...

(function a(x) {
    // The following condition 
    // is the base case.
    if ( ! x) {
        return;
    }
    a(--x);
})(10);
alex
sumber
6
Terima kasih banyak untuk itu..Jadi apakah ada cara / alat yang saya dapat bahwa batas stack sedang habis .. Lagi pula, karena ini adalah file perpustakaan yang sangat besar dan tidak dibuat oleh saya, saya tidak sepenuhnya tahu ke mana hal-hal mungkin salah ..
testndtv
52
@Liver Jika Anda harus menjalankan fungsi hampir 300 triliun kali, Anda mungkin melakukan sesuatu yang salah.
ceejayoz
3
@Liver - Anda mungkin ingin melihat ke dalam pemrograman dinamis - tebakan saya adalah Anda tidak memiliki banyak solusi unik, Anda mengulangi langkah-langkah, jadi Anda mungkin perlu memprogramnya menjadi waktu polinumial daripada kuadratik. en.wikipedia.org/wiki/Dynamic_programming
newshorts
4
@Akhoy Dalam fungsi reguler ya, tetapi pikirkan fungsi rekursif. Ia memanggil yang lain (sendiri) dan meninggalkan alamat pengirim yang sebelumnya di stack (jika tidak ke mana PC tahu ke mana harus pergi?) Ini tentu saja menyebut dirinya lagi, setiap kali mendorong alamat pengirim ke stack. Ketika ini hilang karena kasus dasar yang tidak mungkin terpenuhi di abad berikutnya, Anda mendapatkan stack overflow.
alex
5
Kode Anda menjalankan segmen tidak efisien yang sama sebanyak 134217728 kali. Tidak bercanda lambat. Anda harus menggunakan operator bitwise sehingga Anda dapat membuka gulungan 9 level loop menjadi satu level loop.
Jack Giffin
82

Anda kadang-kadang bisa mendapatkan ini jika Anda secara tidak sengaja mengimpor / menyematkan file JavaScript yang sama dua kali, layak diperiksa di tab sumber daya inspektur Anda.

lucygenik
sumber
9
Masalah ini biasanya terjadi ketika Anda secara tidak sengaja mengimpor / menyematkan file JS yang sama dua kali. Proses persis yang menyebabkan loop rekursif bukanlah sesuatu yang saya ingin berspekulasi, namun saya akan menganggap itu seperti mengendarai dua mobil identik pada kecepatan 100mph melalui gerbang tol yang sama.
lucygenik
3
Saya tidak berpikir ini masalahnya. Jika dua jenis fungsi atau variabel yang sama tertanam, yang terakhir akan mengesampingkan definisi sebelumnya.
ssudaraka
Ya ... Saya tidak benar-benar tahu mengapa itu terjadi atau apa prosesnya, saya akan memiliki meskipun itu akan menimpa juga.
lucygenik
Agak terlambat ke pesta, tetapi akan membayangkan bahwa ketika kode di luar fungsi apa pun, keduanya akan dieksekusi dalam dua file JS, dan satu mungkin tidak akan menimpa satu sama lain karena mereka berada di luar fungsi apa pun.
Cillian Collins
1
@lucygenik lain kali Anda ingin lebih berhati-hati saat menyetujui pengeditan troll pada posting Anda. Posting ini hampir dihapus sebagai spam (periksa riwayat)
Jean-François Fabre
57

Dalam kasus saya, saya mengirim elemen input alih-alih nilainya:

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

Dari pada:

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

Ini membekukan tab Chrome saya ke titik yang bahkan tidak menunjukkan dialog 'Tunggu / Bunuh' ketika halaman menjadi tidak responsif ...

FKasa
sumber
3
Saya ingin tahu mengapa tidak ada pengecualian untuk kesalahan seperti itu ... Terima kasih!
Džuris
Terima kasih banyak, ini menyelamatkan saya
Eme Hado
Saya akan menambahkan ini sebagai solusi yang mungkin. Saya baru saja melakukan ini lol
Michael Buchok
31

Ada loop rekursif di suatu tempat dalam kode Anda (yaitu fungsi yang akhirnya memanggil dirinya sendiri berulang-ulang sampai stack penuh).

Peramban lain memiliki tumpukan yang lebih besar (sehingga Anda mendapatkan batas waktu sebagai gantinya) atau mereka menelan kesalahan karena beberapa alasan (mungkin coba-tangkap yang ditempatkan dengan buruk).

Gunakan debugger untuk memeriksa tumpukan panggilan saat kesalahan terjadi.

Aaron Digulla
sumber
Terima kasih banyak untuk balasan Anda. Di IE / FF, kodenya sepertinya berjalan dengan baik..Hanya di desktop Safari dan iPad Safari, saya mendapatkan kesalahan. Sebenarnya file JS bukan ciptaan saya sendiri, tetapi file perpustakaan (dari DWR engine.js) .. directwebremoting.org Juga ketika Anda mengatakan "debugger untuk memeriksa tumpukan panggilan", bagaimana cara melakukannya menggunakan Inspektur Safari?
testndtv
Saya tidak punya pengalaman dengan Inspektur Safari. Cobalah untuk membuka debugger JavaScript dan muat halaman Anda. Pengawakutu harus berhenti ketika kesalahan yang tidak ditayangkan dilemparkan. Jika itu tidak berhasil, tanyakan pada pengguna super atau webmaster (lihat bagian bawah halaman)
Aaron Digulla
punya 2 fungsi bernama hal yang sama !! DOH!
jharris8567
16

Masalah dengan mendeteksi stackoverflows adalah kadang-kadang jejak stack akan hilang dan Anda tidak akan dapat melihat apa yang sebenarnya terjadi.

Saya telah menemukan beberapa alat debugging baru Chrome yang berguna untuk ini.

Tekan Performance tab, pastikan Javascript samplesdiaktifkan dan Anda akan mendapatkan sesuatu seperti ini.

Cukup jelas di mana limpahannya ada di sini! Jika Anda mengklik extendObjectAnda akan benar-benar dapat melihat nomor baris yang tepat dalam kode.

masukkan deskripsi gambar di sini

Anda juga dapat melihat timing yang mungkin atau mungkin tidak membantu atau herring merah.

masukkan deskripsi gambar di sini


Trik lain yang bermanfaat jika Anda tidak dapat menemukan masalahnya adalah dengan meletakkan banyak console.logpernyataan di tempat yang menurut Anda masalahnya. Langkah sebelumnya di atas dapat membantu Anda dengan ini.

Di Chrome jika Anda berulang kali mengeluarkan data identik, itu akan menampilkannya seperti ini yang menunjukkan di mana masalahnya lebih jelas. Dalam hal ini tumpukan mencapai 7152 frame sebelum akhirnya macet:

masukkan deskripsi gambar di sini

Simon_Weaver
sumber
13

Dalam kasus saya, saya mengubah array byte besar menjadi string menggunakan yang berikut ini:

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

bytes berisi beberapa juta entri, yang terlalu besar untuk muat di tumpukan.

Nate Glenn
sumber
Saya juga punya masalah yang sama dengan baris yang sama !! thanx
ksh
jadi apa solusi terbaik untuk mengubah byte array besar ??
ksh
6
@KarthikHande Anda harus melakukannya dalam for for alih-alih dalam satu panggilan. var uintArray = new Uint16Array(bytes); var converted = []; uintArray.forEach(function(byte) {converted.push(String.fromCharCode(byte))});
Nate Glenn
bagaimana cara mengonversinya menjadi JSON? Saya mencoba JSON.parse tetapi tidak berhasil ... Saya menggunakan Uintl8Array
ksh
@KarthikHande Saya tidak bisa mengatakannya tanpa melihat seluruh masalahnya. Silakan buka pertanyaan lain dengan semua detailnya.
Nate Glenn
6

Dalam kasus saya, acara klik disebarkan pada elemen anak. Jadi, saya harus meletakkan yang berikut ini:

e.stopPropagation ()

pada acara klik:

 $(document).on("click", ".remove-discount-button", function (e) {
           e.stopPropagation();
           //some code
        });
 $(document).on("click", ".current-code", function () {
     $('.remove-discount-button').trigger("click");
 });

Berikut adalah kode html:

 <div class="current-code">                                      
      <input type="submit" name="removediscountcouponcode" value="
title="Remove" class="remove-discount-button">
   </div>
Shahdat
sumber
5

Periksa detail kesalahan di konsol bilah alat dev Chrome, ini akan memberi Anda fungsi di tumpukan panggilan, dan memandu Anda menuju rekursi yang menyebabkan kesalahan.

chim
sumber
3

Hampir setiap jawaban di sini menyatakan bahwa ini hanya dapat disebabkan oleh loop tak terbatas. Itu tidak benar, jika tidak Anda bisa menjalankan stack melalui panggilan yang sangat bersarang (bukan untuk mengatakan itu efisien, tapi itu tentu saja mungkin). Jika Anda memiliki kendali atas JavaScript VM Anda, Anda dapat menyesuaikan ukuran tumpukan. Sebagai contoh:

node --stack-size=2000

Lihat juga: Bagaimana saya dapat meningkatkan ukuran tumpukan panggilan maksimum di Node.js

ghayes
sumber
2

Dalam kasus saya, dua modals jQuery menunjukkan ditumpuk di atas satu sama lain. Mencegah itu menyelesaikan masalah saya.

Barry Guvenkaya
sumber
2

Kami baru-baru ini menambahkan bidang ke situs admin yang sedang kami kerjakan - contact_type ... mudah bukan? Nah, jika Anda memanggil pilih "ketik" dan mencoba mengirimkannya melalui jquery ajax call gagal dengan kesalahan ini terkubur dalam-dalam di jquery.js Jangan lakukan ini:

$.ajax({
    dataType: "json",
    type: "POST",
    url: "/some_function.php",
    data: { contact_uid:contact_uid, type:type }
});

Masalahnya adalah type: type - saya percaya itu adalah kita menamai argumen "type" - memiliki nilai variabel bernama type bukan masalah. Kami mengubah ini menjadi:

$.ajax({
    dataType: "json",
    type: "POST",
    url: "/some_function.php",
    data: { contact_uid:contact_uid, contact_type:type }
});

Dan menulis ulang some_function.php sesuai - masalah terpecahkan.

Scott
sumber
1

Periksa apakah Anda memiliki fungsi yang memanggil dirinya sendiri. Sebagai contoh

export default class DateUtils {
  static now = (): Date => {
    return DateUtils.now()
  }
}
onmyway133
sumber
1

Ini juga dapat menyebabkan Maximum call stack size exceededkesalahan:

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

Sama disini:

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

Dari Mozilla Docs :

Namun berhati-hatilah: dalam menggunakan menerapkan cara ini, Anda berisiko melampaui batas panjang argumen mesin JavaScript. Konsekuensi dari penerapan fungsi dengan terlalu banyak argumen (pikirkan lebih dari puluhan ribu argumen) bervariasi di seluruh mesin (JavaScriptCore memiliki batas argumen hard-kode 65536), karena batas (memang bahkan sifat setiap tumpukan yang terlalu besar) perilaku) tidak ditentukan. Beberapa mesin akan mengeluarkan pengecualian. Lebih parah lagi, orang lain akan secara sewenang-wenang membatasi jumlah argumen yang sebenarnya diteruskan ke fungsi yang diterapkan. Untuk menggambarkan kasus terakhir ini: jika mesin seperti itu memiliki batas empat argumen (batas sebenarnya tentu saja jauh lebih tinggi), itu akan seolah-olah argumen 5, 6, 2, 3 telah dilewati untuk diterapkan dalam contoh di atas, daripada array lengkap.

Jadi cobalah:

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

Kedua doa dari kode yang identik di bawah ini jika dikurangi 1 bekerja di Chrome 32 di komputer saya misalnya 17905 vs 17904. Jika dijalankan seperti itu mereka akan menghasilkan kesalahan "RangeError: Ukuran tumpukan panggilan maksimum terlampaui". Tampaknya batas ini bukan hardcode tetapi tergantung pada perangkat keras mesin Anda. Tampaknya jika dipanggil sebagai fungsi, batas yang dikenakan sendiri ini lebih tinggi daripada jika dipanggil sebagai metode yaitu kode khusus ini menggunakan lebih sedikit memori ketika dipanggil sebagai fungsi.

Dipanggil sebagai metode:

var ninja = {
    chirp: function(n) {
        return n > 1 ? ninja.chirp(n-1) + "-chirp" : "chirp";
    }
};

ninja.chirp(17905);

Dipanggil sebagai fungsi:

function chirp(n) {
    return n > 1 ? chirp( n - 1 ) + "-chirp" : "chirp";
}

chirp(20889);
Elijah Lynn
sumber
0

Anda dapat menemukan fungsi rekursif Anda di browser crome, tekan ctrl + shift + j dan kemudian tab sumber, yang memberi Anda aliran kompilasi kode dan Anda dapat menemukan menggunakan break point dalam kode.

Vishal Patel
sumber
Namun kadang-kadang, bisa sulit untuk mencari tahu dari mana kesalahan itu berasal. Kami memiliki BANYAK JavaScript di situs kami.
Mathias Lykkegaard Lorenzen
0

Saya juga menghadapi masalah serupa di sini adalah detail saat mengunggah logo menggunakan kotak unggah logo dropdown

<div>
      <div class="uploader greyLogoBox" id="uploader" flex="64" onclick="$('#filePhoto').click()">
        <img id="imageBox" src="{{ $ctrl.companyLogoUrl }}" alt=""/>
        <input type="file" name="userprofile_picture"  id="filePhoto" ngf-select="$ctrl.createUploadLogoRequest()"/>
        <md-icon ng-if="!$ctrl.isLogoPresent" class="upload-icon" md-font-set="material-icons">cloud_upload</md-icon>
        <div ng-if="!$ctrl.isLogoPresent" class="text">Drag and drop a file here, or click to upload</div>
      </div>
      <script type="text/javascript">
          var imageLoader = document.getElementById('filePhoto');
          imageLoader.addEventListener('change', handleImage, false);

          function handleImage(e) {
              var reader = new FileReader();
              reader.onload = function (event) {

                  $('.uploader img').attr('src',event.target.result);
              }
              reader.readAsDataURL(e.target.files[0]);
          }
      </script>
      </div>

CSS.css

.uploader {
  position:relative;
  overflow:hidden;
  height:100px;
  max-width: 75%;
  margin: auto;
  text-align: center;

  img{
    max-width: 464px;
    max-height: 100px;
    z-index:1;
    border:none;
  }

  .drag-drop-zone {
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid rgba(0, 0, 0, 0.12);
    padding: 32px;
  }
}

.uploader img{
  max-width: 464px;
  max-height: 100px;
  z-index:1;
  border:none;
}



.greyLogoBox {
  width: 100%;
  background: #EBEBEB;
  border: 1px solid #D7D7D7;
  text-align: center;
  height: 100px;
  padding-top: 22px;
  box-sizing: border-box;
}


#filePhoto{
  position:absolute;
  width:464px;
  height:100px;
  left:0;
  top:0;
  z-index:2;
  opacity:0;
  cursor:pointer;
}

sebelum koreksi kode saya adalah:

function handleImage(e) {
              var reader = new FileReader();
              reader.onload = function (event) {
                  onclick="$('#filePhoto').click()"
                  $('.uploader img').attr('src',event.target.result);
              }
              reader.readAsDataURL(e.target.files[0]);
          }

Kesalahan di konsol:

masukkan deskripsi gambar di sini

Saya menyelesaikannya dengan menghapus onclick="$('#filePhoto').click()"dari tag div.

spacedev
sumber
Di mana Anda menambahkan klik ()
Tsea
0

Saya menghadapi masalah yang sama saya telah mengatasinya dengan menghapus nama bidang yang digunakan dua kali pada ajax misalnya

    jQuery.ajax({
    url : '/search-result',
    data : {
      searchField : searchField,
      searchFieldValue : searchField,
      nid    :  nid,
      indexName : indexName,
      indexType : indexType
    },
.....
Tajdar Khan Afridi
sumber
0

Saya tahu utas ini sudah lama, tetapi saya pikir ada baiknya menyebutkan skenario saya menemukan masalah ini sehingga dapat membantu orang lain.

Misalkan Anda memiliki elemen bersarang seperti ini:

<a href="#" id="profile-avatar-picker">
    <span class="fa fa-camera fa-2x"></span>
    <input id="avatar-file" name="avatar-file" type="file" style="display: none;" />
</a>

Anda tidak dapat memanipulasi peristiwa elemen anak di dalam acara induknya karena itu merambat ke dirinya sendiri, membuat panggilan rekursif sampai pengecualian dilemparkan.

Jadi kode ini akan gagal:

$('#profile-avatar-picker').on('click', (e) => {
    e.preventDefault();

    $('#profilePictureFile').trigger("click");
});

Anda memiliki dua opsi untuk menghindari ini:

  • Pindahkan anak ke luar orangtua.
  • Terapkan fungsi stopPropagation ke elemen child.
Weslley Ramos
sumber
0

Saya memiliki kesalahan ini karena saya memiliki dua Fungsi JS dengan nama yang sama

iceDragon
sumber
0

Jika Anda bekerja dengan google maps, maka periksa apakah lat lng yang diteruskan new google.maps.LatLngmemiliki format yang tepat. Dalam kasus saya mereka disahkan sebagai tidak terdefinisi.

User-8017771
sumber
0

Masalah dalam kasus saya adalah karena saya memiliki rute anak-anak dengan jalur yang sama dengan orang tua:

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    children: [
      { path: '', redirectTo: 'home', pathMatch: 'prefix' },
      { path: 'home', loadChildren: './home.module#HomeModule' },
    ]
  }
];

Jadi saya harus menghapus jalur rute anak-anak

const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    children: [
      { path: 'home', loadChildren: './home.module#HomeModule' },
    ]
  }
];
Amine Harbaoui
sumber
0

dalam kasus saya, saya mendapatkan kesalahan ini pada panggilan ajax dan data yang saya coba berikan variabel itu belum didefinisikan, yang menunjukkan kepada saya kesalahan ini tetapi tidak menggambarkan variabel yang tidak didefinisikan. Saya menambahkan didefinisikan bahwa variabel n mendapat nilai.

asifaftab87
sumber
terbakar dengan cara yang sama sendiri, dalam kasus saya itu karena saya salah ketik nama variabel ... secara efektif hal yang sama.
user2366842
0

Telah menemukan masalah yang sama, coulnd't tahu apa yang salah mulai menyalahkan Babel;)

Memiliki kode yang tidak mengembalikan pengecualian di browser:

if (typeof document.body.onpointerdown !== ('undefined' || null)) {

masalah ini dibuat dengan buruk || (atau) bagian ketika babel membuat pemeriksaan tipenya sendiri:

function _typeof(obj){if(typeof Symbol==="function"&&_typeof(Symbol.iterator)==="symbol")

jadi hapus

|| null

membuat transpilasi babel bekerja.

Raphael
sumber
0

Dalam kasus saya saya karena kesalahan saya telah menetapkan nama variabel yang sama, dan untuk fungsi val "class_routine_id"

var class_routine_id = $("#class_routine_id").val(class_routine_id);

itu harus seperti:

 var class_routine_id = $("#class_routine_id").val(); 
Alok Jha
sumber
0

Saya menggunakan React-Native 0.61.5 bersama dengan ( npm 6.9.0 & node 10.16.1 )

Sementara saya menginstal perpustakaan baru di Proyek saya mendapat dari

(mis. npm instal @ react-navigation / native --save)

Ukuran tumpukan panggilan maksimum melebihi kesalahan

untuk itu, saya coba

sudo npm cache clean --force

(Catatan: - Perintah di bawah ini biasanya membutuhkan waktu 1 hingga 2 menit tergantung pada ukuran cache npm Anda )

DevAelius
sumber
-1

Terkadang terjadi karena konversi tipe data, misalnya Anda memiliki objek yang Anda anggap sebagai string.

socket.id di nodejs baik di js client sebagai contoh, bukan string. untuk menggunakannya sebagai string, Anda harus menambahkan kata String sebelum:

String(socket.id);
Hussein mahyoub
sumber
-1

Saya mencoba untuk menetapkan variabel, nilai, ketika variabel itu belum dideklarasikan.

Mendeklarasikan variabel memperbaiki kesalahan saya.

Phillip Quinlan
sumber