Unable to set global variable from function

I am trying to create a function that increments a padded counter like “001”, but I can’t seem to set my global variable from within the function.

  // Initialize step number
  let step = "001";

  // Print vuser number and iteration count
  console.log(`VU: ` + vuser + ` ITER: ` + iter + ` STEP: ` + step + ` START`);

  res = http.get(`https://` + tenant, {
    tags: { name: step + ` - https://` + tenant },
  });
  checkStatus(res, vuser, iter, step, 302);
  stepInc(step);

function stepInc(step) {
  step = parseFloat(step);
  step++;
  step = step.toString();
  step = step.padStart(3, '0');
}

The function resolves all of the transformations of step correctly, but I can’t seem to write it back to the global variable step. Am I missing something here?

Ideally, I would call stepInc() from within checkStatus(), but I can’t even get this to work.

Hello!

In JavaScript, primitives (like numbers) are passed by value, while objects are passed by reference. In order to do what you’re wanting, you’d have to write something like this:

let step = {};
step.num = 0;

export default function() {
  console.log("step.num: " + step.num);
  incStep(step);
}

function incStep(step) {
  step.num++;
}

Not particularly intuitive if, like me, you’re coming from a C#/Java background…!

Hmm… now how would I call this from within another function? I have tried ${step.num}, but it wasn’t too happy about that.

function checkStatus(res, vuser, iter, step, code) {
  check(res, {
    "Status: OK": (res) => res.status === code,

  }) || fail(" - - - Checks failed: " + res.url + " - - - Expected: " + code + " - - - Received: " + res.status + ` (vuser: ` + vuser + `, iter: ` + iter + `) ` + res.body);

  // Print out the current step to the console
  console.log(`VU: ` + vuser + ` ITER: ` + iter + ` STEP: ` + `${step}` + `-` + res.url)

  stepInc( ??? );

  sleep(2);
}

We’ll need a more complete code sample to figure out what you’re trying to do (i.e. your step declaration, but ideally you’re whole script minus anything sensitive).

You have no idea how much I appreciate this help, btw.

So below is my hacky workaround. What I am trying to have have happen is:

  1. The checkStatus() function should call the stepInc() function.
  2. The stepInc() function should read the global variable step and read/set it directly.
    // Compare the HTTP code retuned with what is expected, and fail the step if it does not match
    function checkStatus(res, vuser, iter, step, code) {
      check(res, {
        "Status: OK": (res) => res.status === code,

      }) || fail(" - - - Checks failed: " + res.url + " - - - Expected: " + code + " - - - Received: " + res.status + ` (vuser: ` + vuser + `, iter: ` + iter + `) ` + res.body);

      // Print out the current step to the console
      console.log(`VU: ` + vuser + ` ITER: ` + iter + ` STEP: ` + `${step}` + `-` + res.url)

      sleep(2);
    }

    function stepInc(step) {
      step = parseFloat(step);
      step++;
      step = step.toString();
      step = step.padStart(3, '0');
    }

      // Initialize step number
     let step = 1;

      // Print vuser number and iteration count
      console.log(`VU: ` + vuser + ` ITER: ` + iter + ` STEP: ` + step + ` START`);

      res = http.get(`https://` + tenant, {
        tags: { name: `00` + step + ` - https://` + tenant },
      });
      checkStatus(res, vuser, iter, step, 302);
      step++;

      res = http.get(`https://` + tenant + `/Platform/`, {
        tags: { name: `00` + step + ` - https://` + tenant + `/Platform/` },
      });
      checkStatus(res, vuser, iter, step, 302);
      step++;

Hi @leathej1 ,

From the latest code that you’ve posted step doesn’t look to be global.

If it is global - defined on the same levels as export default function() ... as in :

import http from "k6/http";
let step = 0; // this is global variable
export default function() {
   // here you can do w/e with step and if you haven't define one in 
   // the scope of this function it will change the global one
   step++; // this touches the global
}

function touchLocalStep(step) { // here step is an argument and is *not* the global one
  step++ // touches the local argument, which is copied by value as argument so it won't be seen outside the function
}

so you can either have it be global or you can have it locally (or have it both, but it will be a different variable).

As far as I can see from your sample you can just step++ wherever you want and when you will be using it you can have a formatStep as in

function formatStep(arg) { // I specifically changed it to not be called `step` here
      return arg.toString().padStart(3, '0');
}

and now you can move the definition of step in the default function, so it is local for that function, do step++ where you need to increase it and whenever you need to have it as a string with leading 0 call fortmatStep(step) and use the result instead.

Hope this helps you

Oh, wow - how did I miss that it wasn’t at the same level as the default function…

You saved me again- thanks!