Saya ingin menangkap setiap kesalahan fungsi yang tidak terdefinisi. Apakah ada fasilitas penanganan kesalahan global dalam JavaScript? Kasus penggunaan menangkap panggilan fungsi dari flash yang tidak ditentukan.
Saya ingin menangkap setiap kesalahan fungsi yang tidak terdefinisi. Apakah ada fasilitas penanganan kesalahan global dalam JavaScript? Kasus penggunaan menangkap panggilan fungsi dari flash yang tidak ditentukan.
Jawaban:
Apakah ini membantu Anda:
<script type="text/javascript">
window.onerror = function() {
alert("Error caught");
};
xxx();
</script>
Saya tidak yakin bagaimana menangani kesalahan Flash ...
Pembaruan: tidak berfungsi di Opera, tapi saya meretas Dragonfly sekarang untuk melihat apa yang didapatnya. Saran tentang peretasan Dragonfly datang dari pertanyaan ini:
window.onerror = function() { alert(42) };
sekarang kode dalam jawaban: window.onerror = function() { alert("Error caught"); };
tidak diganti, saya masih tidak yakin ..
Tetapkan window.onerror
acara ke pengendali acara seperti:
<script type="text/javascript">
window.onerror = function(msg, url, line, col, error) {
// Note that col & error are new to the HTML 5 spec and may not be
// supported in every browser. It worked for me in Chrome.
var extra = !col ? '' : '\ncolumn: ' + col;
extra += !error ? '' : '\nerror: ' + error;
// You can view the information in an alert to see things working like this:
alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);
// TODO: Report this error via ajax so you can keep track
// of what pages have JS issues
var suppressErrorAlert = true;
// If you return true, then error alerts (like in older versions of
// Internet Explorer) will be suppressed.
return suppressErrorAlert;
};
</script>
Seperti yang dikomentari dalam kode, jika nilai baliknya window.onerror
adalah true
maka browser harus menekan menampilkan dialog peringatan.
Singkatnya, acara dinaikkan ketika 1.) ada pengecualian atau 2.) kesalahan waktu kompilasi terjadi.
pengecualian tanpa tertangkap
- melempar "beberapa pesan"
- call_something_undefined ();
- cross_origin_iframe.contentWindow.document ;, pengecualian keamanan
kompilasi kesalahan
<script>{</script>
<script>for(;)</script>
<script>"oops</script>
setTimeout("{", 10);
, ia akan mencoba untuk mengkompilasi argumen pertama sebagai skrip
Contoh kode onerror di atas dalam tindakan setelah menambahkan ini ke halaman pengujian:
<script type="text/javascript">
call_something_undefined();
</script>
var error_data = {
url: document.location.href,
};
if(error != null) {
error_data['name'] = error.name; // e.g. ReferenceError
error_data['message'] = error.line;
error_data['stack'] = error.stack;
} else {
error_data['msg'] = msg;
error_data['filename'] = filename;
error_data['line'] = line;
error_data['col'] = col;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/ajax/log_javascript_error');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
console.log('JS error logged');
} else if (xhr.status !== 200) {
console.error('Failed to log JS error.');
console.error(xhr);
console.error(xhr.status);
console.error(xhr.responseText);
}
};
xhr.send(JSON.stringify(error_data));
https://jsfiddle.net/nzfvm44d/
throw
dibuat secara manual. stackoverflow.com/questions/15036165/…
Jika penanganan kesalahan Anda sangat canggih dan karena itu mungkin menimbulkan kesalahan itu sendiri, ada baiknya menambahkan tanda yang menunjukkan jika Anda sudah dalam "errorHandling-Mode". Seperti itu:
var appIsHandlingError = false;
window.onerror = function() {
if (!appIsHandlingError) {
appIsHandlingError = true;
handleError();
}
};
function handleError() {
// graceful error handling
// if successful: appIsHandlingError = false;
}
Kalau tidak, Anda bisa menemukan diri Anda dalam loop tak terbatas.
handleError
metode.
Coba Atatus yang menyediakan Pelacakan Kesalahan Tingkat Lanjut dan Pemantauan Pengguna Nyata untuk aplikasi web modern.
Biarkan saya menjelaskan cara mendapatkan stacktraces yang cukup lengkap di semua browser.
Modern Chrome dan Opera sepenuhnya mendukung spesifikasi draft HTML 5 untuk ErrorEvent dan window.onerror
. Di kedua browser ini, Anda dapat menggunakan window.onerror
, atau mengikat acara 'kesalahan' dengan benar:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Sayangnya Firefox, Safari dan IE masih ada dan kami harus mendukungnya juga. Karena stacktrace tidak tersedia, window.onerror
kita harus melakukan sedikit lebih banyak pekerjaan.
Ternyata satu-satunya hal yang bisa kita lakukan untuk mendapatkan stacktraces dari kesalahan adalah dengan membungkus semua kode kita dalam sebuah try{ }catch(e){ }
blok dan kemudian melihatnya e.stack
. Kita dapat membuat prosesnya lebih mudah dengan fungsi yang disebut wrap yang mengambil fungsi dan mengembalikan fungsi baru dengan penanganan kesalahan yang baik.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
Ini bekerja. Setiap fungsi yang Anda bungkus secara manual akan memiliki penanganan kesalahan yang baik, tetapi ternyata kami benar-benar dapat melakukannya untuk Anda secara otomatis dalam banyak kasus.
Dengan mengubah definisi global addEventListener
sehingga secara otomatis membungkus panggilan balik kita dapat secara otomatis memasukkan try{ }catch(e){ }
sekitar sebagian besar kode. Ini memungkinkan kode yang ada terus berfungsi, tetapi menambahkan pelacakan pengecualian berkualitas tinggi.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
Kita juga harus memastikan itu removeEventListener
tetap bekerja. Saat ini tidak akan karena argumen untuk addEventListener
diubah. Sekali lagi kita hanya perlu memperbaiki ini pada prototype
objek:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Anda dapat mengirim data kesalahan menggunakan tag gambar sebagai berikut
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
Penafian: Saya seorang pengembang web di https://www.atatus.com/ .
http://yourserver.com
) untuk menerima dan menyimpan. Jika Anda memilih atatus.com , Anda tidak perlu melakukan apa pun. Cukup sertakan dua baris skrip di halaman Anda.
Tampaknya window.onerror
tidak memberikan akses ke semua kemungkinan kesalahan. Secara khusus itu mengabaikan:
<img>
memuat kesalahan (respons> = 400).<script>
memuat kesalahan (respons> = 400).window.onerror
dengan cara yang tidak diketahui (jquery, angular, dll.).Inilah awal skrip yang menangkap banyak kesalahan ini, sehingga Anda dapat menambahkan lebih banyak debugging yang kuat ke aplikasi Anda selama pengembangan.
(function(){
/**
* Capture error data for debugging in web console.
*/
var captures = [];
/**
* Wait until `window.onload`, so any external scripts
* you might load have a chance to set their own error handlers,
* which we don't want to override.
*/
window.addEventListener('load', onload);
/**
* Custom global function to standardize
* window.onerror so it works like you'd think.
*
* @see http://www.quirksmode.org/dom/events/error.html
*/
window.onanyerror = window.onanyerror || onanyerrorx;
/**
* Hook up all error handlers after window loads.
*/
function onload() {
handleGlobal();
handleXMLHttp();
handleImage();
handleScript();
handleEvents();
}
/**
* Handle global window events.
*/
function handleGlobal() {
var onerrorx = window.onerror;
window.addEventListener('error', onerror);
function onerror(msg, url, line, col, error) {
window.onanyerror.apply(this, arguments);
if (onerrorx) return onerrorx.apply(null, arguments);
}
}
/**
* Handle ajax request errors.
*/
function handleXMLHttp() {
var sendx = XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.send = function(){
handleAsync(this);
return sendx.apply(this, arguments);
};
}
/**
* Handle image errors.
*/
function handleImage() {
var ImageOriginal = window.Image;
window.Image = ImageOverride;
/**
* New `Image` constructor. Might cause some problems,
* but not sure yet. This is at least a start, and works on chrome.
*/
function ImageOverride() {
var img = new ImageOriginal;
onnext(function(){ handleAsync(img); });
return img;
}
}
/**
* Handle script errors.
*/
function handleScript() {
var HTMLScriptElementOriginal = window.HTMLScriptElement;
window.HTMLScriptElement = HTMLScriptElementOverride;
/**
* New `HTMLScriptElement` constructor.
*
* Allows us to globally override onload.
* Not ideal to override stuff, but it helps with debugging.
*/
function HTMLScriptElementOverride() {
var script = new HTMLScriptElement;
onnext(function(){ handleAsync(script); });
return script;
}
}
/**
* Handle errors in events.
*
* @see http://stackoverflow.com/questions/951791/javascript-global-error-handling/31750604#31750604
*/
function handleEvents() {
var addEventListenerx = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = addEventListener;
var removeEventListenerx = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = removeEventListener;
function addEventListener(event, handler, bubble) {
var handlerx = wrap(handler);
return addEventListenerx.call(this, event, handlerx, bubble);
}
function removeEventListener(event, handler, bubble) {
handler = handler._witherror || handler;
removeEventListenerx.call(this, event, handler, bubble);
}
function wrap(fn) {
fn._witherror = witherror;
function witherror() {
try {
fn.apply(this, arguments);
} catch(e) {
window.onanyerror.apply(this, e);
throw e;
}
}
return fn;
}
}
/**
* Handle image/ajax request errors generically.
*/
function handleAsync(obj) {
var onerrorx = obj.onerror;
obj.onerror = onerror;
var onabortx = obj.onabort;
obj.onabort = onabort;
var onloadx = obj.onload;
obj.onload = onload;
/**
* Handle `onerror`.
*/
function onerror(error) {
window.onanyerror.call(this, error);
if (onerrorx) return onerrorx.apply(this, arguments);
};
/**
* Handle `onabort`.
*/
function onabort(error) {
window.onanyerror.call(this, error);
if (onabortx) return onabortx.apply(this, arguments);
};
/**
* Handle `onload`.
*
* For images, you can get a 403 response error,
* but this isn't triggered as a global on error.
* This sort of standardizes it.
*
* "there is no way to get the HTTP status from a
* request made by an img tag in JavaScript."
* @see http://stackoverflow.com/questions/8108636/how-to-get-http-status-code-of-img-tags/8108646#8108646
*/
function onload(request) {
if (request.status && request.status >= 400) {
window.onanyerror.call(this, request);
}
if (onloadx) return onloadx.apply(this, arguments);
}
}
/**
* Generic error handler.
*
* This shows the basic implementation,
* which you could override in your app.
*/
function onanyerrorx(entity) {
var display = entity;
// ajax request
if (entity instanceof XMLHttpRequest) {
// 400: http://example.com/image.png
display = entity.status + ' ' + entity.responseURL;
} else if (entity instanceof Event) {
// global window events, or image events
var target = entity.currentTarget;
display = target;
} else {
// not sure if there are others
}
capture(entity);
console.log('[onanyerror]', display, entity);
}
/**
* Capture stuff for debugging purposes.
*
* Keep them in memory so you can reference them
* in the chrome debugger as `onanyerror0` up to `onanyerror99`.
*/
function capture(entity) {
captures.push(entity);
if (captures.length > 100) captures.unshift();
// keep the last ones around
var i = captures.length;
while (--i) {
var x = captures[i];
window['onanyerror' + i] = x;
}
}
/**
* Wait til next code execution cycle as fast as possible.
*/
function onnext(fn) {
setTimeout(fn, 0);
}
})();
Ini bisa digunakan seperti ini:
window.onanyerror = function(entity){
console.log('some error', entity);
};
Script lengkap memiliki implementasi default yang mencoba untuk mencetak versi "display" semi-readable dari entitas / kesalahan yang diterimanya. Dapat digunakan untuk inspirasi bagi penangan kesalahan khusus aplikasi. Implementasi default juga menyimpan referensi ke 100 entitas kesalahan terakhir, sehingga Anda dapat memeriksanya di konsol web setelah terjadi seperti:
window.onanyerror0
window.onanyerror1
...
window.onanyerror99
Catatan: Ini berfungsi dengan mengganti metode pada beberapa peramban / konstruktor asli. Ini dapat memiliki efek samping yang tidak diinginkan. Namun, telah berguna untuk digunakan selama pengembangan, untuk mencari tahu di mana kesalahan terjadi, untuk mengirim log ke layanan seperti NewRelic atau Sentry selama pengembangan sehingga kami dapat mengukur kesalahan selama pengembangan, dan pada pementasan sehingga kami dapat men-debug apa yang sedang terjadi di tingkat yang lebih dalam. Kemudian dapat dimatikan dalam produksi.
Semoga ini membantu.
Seseorang harus mempertahankan callback onerror sebelumnya terkait juga
<script type="text/javascript">
(function() {
var errorCallback = window.onerror;
window.onerror = function () {
// handle error condition
errorCallback && errorCallback.apply(this, arguments);
};
})();
</script>
Jika Anda ingin cara terpadu untuk menangani kesalahan yang tidak tertangkap dan penolakan janji yang tidak ditangani, Anda dapat melihat di perpustakaan yang tidak tertangkap .
EDIT
<script type="text/javascript" src=".../uncaught/lib/index.js"></script>
<script type="text/javascript">
uncaught.start();
uncaught.addListener(function (error) {
console.log('Uncaught error or rejection: ', error.message);
});
</script>
Itu mendengarkan jendela. penolakan unhandled selain window.onerror.
Saya akan merekomendasikan mencoba Trackjs .
Galat saat masuk sebagai layanan.
Sangat sederhana untuk diatur. Cukup tambahkan satu baris <script> ke setiap halaman dan hanya itu. Ini juga berarti akan sangat mudah untuk dihapus jika Anda memutuskan tidak menyukainya.
Ada layanan lain seperti Sentry (yang merupakan open-source jika Anda dapat meng-host server Anda sendiri), tetapi tidak melakukan apa yang Trackjs lakukan. Trackjs merekam interaksi pengguna antara browser mereka dan server web Anda sehingga Anda benar-benar dapat melacak langkah-langkah pengguna yang menyebabkan kesalahan, bukan hanya referensi file dan nomor baris (dan mungkin stack trace).
Anda mendengarkan acara onerror dengan menetapkan fungsi ke window.onerror:
window.onerror = function (msg, url, lineNo, columnNo, error) {
var string = msg.toLowerCase();
var substring = "script error";
if (string.indexOf(substring) > -1){
alert('Script Error: See Browser Console for Detail');
} else {
alert(msg, url, lineNo, columnNo, error);
}
return false;
};