1

I'm working on making a modification to a node.js module to improve error handling for one of my uses cases. The specifics of the module aren't really relevant, but one of the things I want to do is trigger a delayed retry when receiving a certain status code from the response to an API request. To do this I'm using the timeOut function to trigger a new call to the function after a period of time.

The structure of the code looks like this:

Outer function (parameters specified by client application)
 ——API request (using parameters)
   ——Callback from API request (response with status code)
     ——If error, set timeout to call outer function after delay

However, I also want to handle the case that the outer function is called again while waiting for the timeout. I don't want any calls to trigger a new API request while a timeout is pending, but I do want the parameters from the most recent call to be used when the timeout finishes.

I've been able to get this working using variables that are global to the module. Each time a new call comes in to the outer function it updates a global object with the new parameters then, if a timeout is pending, returns without calling the API request. The timeout function uses the parameters from the global object to call the outer function, rather than the parameters from when it was set. This way it always uses the most recent values that were passed into the outer function, but doesn't make duplicate API calls.

Here's a simplified example of how I've achieved this behavior with global variables: JSFiddle. Hit run a few times until you get a "failure response" which then triggers the timeout.

This works, but I would prefer not add these global variables into the module if there's a better way.

Is there any way to get this same behavior but have all of the state encapsulated in the outer function without using globals? I'm also open to completely rethinking the way I'm handling this if anyone has ideas.

1 Answer 1

1

You're not going to be able to do this without creating variables outside of your outer function, however it's still possible to create those variables without polluting your global scope.

To do so, wrap your outer function in another function that gets executed immediately, sometimes known as an IIFE:

mainFunction: (function() {
    var savedParam1;
    var savedParam2;
    var savedParam3;
    var pendingTimeout = false;

    return function(param1, param2, param3) {
        savedParam1 = param1;
        savedParam2 = param2;
        savedParam3 = param3;

        if (pendingTimeout) {
            log('pending timeout -- ignoring new call');
            return;
        }

        /* and so on */

    }
})(); // the () causes the outer function to run immediately,
      // which creates a scope for the savedParam / pendingTimeout variables, 
      // and then returns the inner function (your old outer function)
      // to be used for mainFunction
Sign up to request clarification or add additional context in comments.

3 Comments

This looks like exactly what I was trying for, thanks. I'll test it out tonight when I have a chance. I had tried something similar and it didn't work, but I think the way you structured it will.
This is a good answer, you should also read about clousure because the scope could be a little tricky.
This worked, but I had to also pass the savedParams into the inner function (from the JSFiddle). I also put them into a single object (function(state, savedParams) { .... })(this, savedParams)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.