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)


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);

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.


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 ...


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.


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


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.


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>

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.



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


2

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


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.


1

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

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

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]);
}

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);

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.


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.


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
    },
.....

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.

0

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


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.


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' },
    ]
  }
];

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.


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.


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(); 


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 )


-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);

-1

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

Mendeklarasikan variabel memperbaiki kesalahan saya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.