Как сделать jQuery Ajax Error Catch и сообщить - PullRequest
2 голосов
/ 28 июня 2019

Каким образом получить вызывающую функцию события ajaxError, созданного для отчетов об ошибках js?

Я создал приложение репозитория ошибок js с jQuery, и я могу обрабатывать обычные ошибки js, возникающие во всем мире, но у меня есть проблемы с ошибками ajax. Я могу получить номер строки ошибки, когда это нормальная ошибка! Я пытался поймать их с помощью одного из глобальных обработчиков ajax "ajaxError", но я не уверен, как получить номер строки этого вызывающего абонента ajax или имя вызывающего абонента.

пожалуйста, посмотрите на нижнюю часть!

const error_log_url = '/log';
const errorPost = function (data) {
    $.ajax({
         url: error_log_url,
         type: 'post',
         data: data,
         success: function (res) {
             console.log(res)
         }, error: function (res) {
            console.log(res)
         }
     })
 }
 window.addEventListener('error', function (e) {

     let params = {
         message: e.message || "Exception Handler",
         url: e.filename || "",
         lineno: e.lineno || 0,
         colno: e.colno || 0
     }

     errorPost(params)
 }, true);

 // wrap function for new error stack with adding event to certain element
 window.wrap = function (func) {
    // make sure you only wrap the function once
    if (!func._wrapped) {
        func._wrapped = function () {
            try {
                func.apply(this, arguments);
            } catch (exception) {
                throw exception
            }
        }
    }
    return func._wrapped;
 }

 // override add & remove event listeners with above wrap function
 let addEvenListener = window.EventTarget.prototype.addEventListener;
 window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
    addEvenListener.call(this, event, wrap(callback), bubble);
 }

 let removeEventLister = window.EventTarget.prototype.removeEventListener;
 window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
    removeEventLister.call(this, event, callback._wrapped || callback, bubble);
 }

 $(document).ajaxError(function( event, jqxhr, settings, thrownError ) {

     // please look at here, how can I get the caller name that produced this error!
     console.log(arguments.callee.caller)

     if (settings.url != error_log_url)
         errorPost({
             message: event.type,
             filename: event.currentTarget.location.origin + settings.url
         })


 });

console.log (arguments.callee.caller) выводит ноль.

вы видите, я могу получить гораздо больше информации от ErrorEvent, но я не могу получить подробную информацию, такую ​​как номер строки из события ajaxError!

1 Ответ

1 голос
/ 28 июня 2019

К сожалению, похоже, что нет глобального события для сетевых ошибок.

Существует хакерский способ выяснить это, хотя - если вы присоединяете функцию к методу ajaxSend, который запускается при отправке запроса, вы можете немедленно выдать ошибку , а затем перехватить это и исследует стек, чтобы выяснить вызывающего. Затем поместите соответствующую строку стека в WeakMap, которая может быть исследована позже, проиндексирована объектом jqXHR. После этого, если запрос не выполняется, в обработчике ajaxError используйте его объект jqXHR для поиска стека в WeakMap. Например:

$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
  console.log(stacksByXHR.get(jqxhr));
});
const stacksByXHR = new WeakMap();
$(document).ajaxSend((event, jqXHR) => {
  try {
    throw new Error();
  } catch({ stack }) {
    let callCountNonJquery = 0;
    const foundCall = stack
      .split('\n')
      .slice(1) // Remove the top "Error" line, contains no information
      .find(line => {
        if (line.includes('jquery')) {
          return false;
        }
        callCountNonJquery++;
        // First call would be the thrown error above
        // Second call is the $.ajax initiator
        if (callCountNonJquery === 2) {
          return true;
        }
      });
    stacksByXHR.set(jqXHR, foundCall);
  }
});
$.ajax('/DoesNotExist');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

На моей машине это показывает мне

at https://stacksnippets.net/js:40:3

, что соответствует строке $.ajax('/DoesNotExist');:

enter image description here

Если $.ajax находится внутри функции, имя функции будет также отображаться в стеке, например:

$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
  console.log(stacksByXHR.get(jqxhr));
});
const stacksByXHR = new WeakMap();
$(document).ajaxSend((event, jqXHR) => {
  try {
    throw new Error();
  } catch({ stack }) {
    let callCountNonJquery = 0;
    const foundCall = stack
      .split('\n')
      .slice(1) // Remove the top "Error" line, contains no information
      .find(line => {
        if (line.includes('jquery')) {
          return false;
        }
        callCountNonJquery++;
        // First call would be the thrown error above
        // Second call is the $.ajax initiator
        if (callCountNonJquery === 2) {
          return true;
        }
      });
    stacksByXHR.set(jqXHR, foundCall);
  }
});
function myFunctionWhichRunsAjax() {
  $.ajax('/DoesNotExist');
}
myFunctionWhichRunsAjax();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
...