Nested arrow function gets global scope

280 Views Asked by At

Here's a simplified version of the code:

class Service {
    static _runRequest = (request, success, failure) => {
        request.then(
            (response) => {
                if (ResponseHelper.wasSuccessful(response)) {
                    success(response);
                }
                else if (ResponseHelper.wasUnauthorized(response)) {
                    SessionHelper.refreshCurrentSession().then(
                        (refreshResponse) => {
                            if (refreshResponse === true) {
                                this._runRequest(request, success, failure);
                            }
                        }
                    );
                }
            }
        );
    }
}

The issue is that, when calling _runRequest again if the session was refreshed successfully, this is pointing to the global scope.

Any ideas why and how to fix this? Shouldn't this stay the same no matter how many nested functions there are?

1

There are 1 best solutions below

0
On

In your code this will be the global object or undefined (depending on strict settings & environment), independent of the nesting level you are in. It is like that as soon as you execute the first line in the static method.

Instead of defining the static method with the arrow syntax, use the more established, short-cut function notation:

static _runRequest(request, success, failure) { // ...etc

This will make this refer to the "class" object.

See below for a comparison of the two ways of defining the static method, with simplified code (no nesting, no promises) using Babel:

class Service1 {
    static _runRequest = (i) => {
        if (i == 0) {
          console.log('zero');
          return;
        }
        if (this && '_runRequest' in this) {
           return this._runRequest(0); // recurse
        }
        console.log('this is ' + this);
    }
}

Service1._runRequest(1);

class Service2 {
    static _runRequest(i) {
        if (i == 0) {
          console.log('zero');
          return;
        }
        if (this && '_runRequest' in this) {
           return this._runRequest(0); // recurse
        }
        console.log('this is ' + this);
    }
}

Service2._runRequest(1);