2

I have a function that returns a promise, like this. From within the promise callback (.then or .catch, I want to be able to find the name of the original function ("myFunction"). How can I do this?

function myFunction() {
  return fetch('https://example.com')
    // The promise will fail because Stackoverflow is sandboxed
    .catch(function() {
      console.log(JSON.stringify(arguments.callee.name))
      // It is returning the name of my anonymous function ("").
      // I want it to log "myFunction" instead.
    })
}

myFunction();
Ethan
  • 3,410
  • 1
  • 28
  • 49
  • 1
    I’m struggling to see the use case or purpose of why you’d need this. – Charlie Fish Oct 11 '18 at 04:44
  • @CharlieFish A handleError function gets called inside the `.then`. I am providing the function with instructions on how to call the original function again. So I need to provide the function name and arguments. – Ethan Oct 11 '18 at 04:46
  • but even if you store the function name in a variable, I don’t think you can call a function based on the value of a variable that corosponds to the function name you want to run. – Charlie Fish Oct 11 '18 at 04:47
  • but the function name is `myFunction`, because that's what you called it when you wrote it - still not clear why you would need it – Jaromanda X Oct 11 '18 at 04:47
  • @CharlieFish yes you can... https://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string – Ethan Oct 11 '18 at 04:48
  • @JaromandaX I have to do this for ~15 different functions, it is much easier to have the same piece of code for each. – Ethan Oct 11 '18 at 04:49
  • 2
    just make sure you don't "use strict" - because then the answer below won't work either – Jaromanda X Oct 11 '18 at 04:50
  • 1
    Why the downvote here? – Benjamin Gruenbaum Oct 11 '18 at 09:27

2 Answers2

3

You can just save the arguments to another variable outside the catch closure.

function myFunction() {
  let args = arguments;
  return fetch('https://example.com')
    // The promise will fail because Stackoverflow is sandboxed
    .catch(function() {
      console.log(JSON.stringify(args.callee.name))
      // It is returning the name of my anonymous function ("").
      // I want it to log "myFunction" instead.
    })
}

myFunction();
choz
  • 17,242
  • 4
  • 53
  • 73
  • 2
    might wanna mention that this is deprecated: https://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript/235760#235760 – nem035 Oct 11 '18 at 04:42
  • 1
    @nem035 Thank you, I just noticed that as well. Will read a bit and add it to post if its related – choz Oct 11 '18 at 04:45
  • @nem035 It is indeed that [arguments.caller is obsolete](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller). But in this case, since `arguments.callee` returns the `Function` itself, OP solution to call [arguments.callee.caller](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller) is still good. In fact, this property replaces the obsolete `arguments.caller` property of the `arguments` object. – choz Oct 11 '18 at 04:56
2

There is no way to do this that works in strict mode and isn't deprecated (as choz said). This is quite intentional and is done in order to be able to prevent potential leaks and enable things like SES. It also breaks with minifiers.

There is already a good answer by choz explaining how to do this in loose mode and old environments.

It is possible to obtain this from the stack trace with async stack traces when using async functions (by using new Error().stack) which is guaranteed to work and is future proof. However, there are no plans to develop async stack traces for promises when not using async await and async stack traces for production literally landed in V8 last week so it'll take time before it is usable.

If you use babel or TypeScript it's also possible to do this through a code transform and a plugin.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504