Abhinav Galodha
Abhinav Galodha

Reputation: 9878

How to identify the caller function name in an AJAX or XMLHttpRequest call?

I am trying to find out how to identify the function name which initiated the Ajax call programmatically using JavaScript or jQuery for an existing code base.

I am working on the instrumentation of an existing large code base and hence trying to identify the function name which correlates with the AJAX requests. So, there is already a lot of code and modifying each method doesn't seem to be the best approach. So, I am trying to think about a generic approach which can work for all the methods. The code already has a generic wrapper around the AJAX call, so I can hook into the entry and exit points of the method.

For e.g. in below code, in the always function, I need to know the initiator function name or the call stack.

function ajaxWrapper(){
var jqxhr = $.ajax( "https://jsonplaceholder.typicode.com/posts/1" )
  .done(function() {
    console.log( "success" );
  })
  .fail(function() {
    console.log( "error" );
  })
  .always(function() {
    console.log( "complete" );
   // TODO: Who Initiated the call ?
  });
}

function initiator1(){
	initiator2();
}

function initiator2(){
	ajaxWrapper();
}

initiator1();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

What have I tried?

  1. I know one approach is using setting the custom headers in the beforeSend method and the always callback receives the jqXHR object as the parameter. But this doesn't seem to be suitable approach as I can't modify all the functions to send the method name as a parameter.

  2. arguments.callee.caller approach, but it doesn't seem to work in case of the Asynchronous methods. Also, this feature seems to be deprecated because of performance and security reasons.

Note: I am not looking this information for debugging purpose. I am already aware of the Async call stack, Initiator and console.trace solutions available in developers tool.

Upvotes: 3

Views: 3171

Answers (1)

Alin P.
Alin P.

Reputation: 44346

One option is to generate the call stack inside your wrapper, because up to that point you are in a sync function call chain.

var err = new Error();
var stack = err.stack;

And use it later in the callback, because it's available as part of a higher scope. (Scopes don't care about async.)

You'll need to do some parsing (browser specific unfortunately) on that call stack. I don't know what you intend to do with the initiator, but you may want to keep all the chain, not just the first one.

Also note that this technique is unreliable and you shouldn't use it for anything critical.

function ajaxWrapper(){
var err = new Error();
var stack = err.stack;
var jqxhr = $.ajax( "https://jsonplaceholder.typicode.com/posts/1" )
  .done(function() {
    console.log( "success" );
  })
  .fail(function() {
    console.log( "error" );
  })
  .always(function() {
    console.log( "complete" );
    // TODO: Who Initiated the call ?
    console.log(stack);
  });
}

function initiator1(){
	initiator2();
}

function initiator2(){
	ajaxWrapper();
}

initiator1();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 2

Related Questions