0

I have a requirement to have some callouts from LWC. So, I created a generic callout method in util file with XHR request.

Now, I want to pass my showSpinner flag to the util method, which I'll use to control the original spinner.

I thought it will go as a reference however, it is not working.

I'm primarily looking for an effective way(without passing as a param) to pass the variable from LWC to utility JS methods and manipulate data from that JS.

Here is the sample util method -

function performCallout(method, endpoint, data, token, showSpinner) {
    if (data == null) return;
    console.log('value of spinner is ', showSpinner);
    let xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function(showSpinner) {  //i tried removing showSpinner.     

        if (this.readyState == 4 && this.status == 200) {
            showSpinner = false; //this is not working. Even I tried to pass LWC function as a param and call here. 
            console.log(JSON.stringify(xhttp.responseText));
        }
    };
    xhttp.open(method, endpoint, true); 
    xhttp.setRequestHeader("Access-Control-Allow-Origin", "*");
    xhttp.setRequestHeader("Content-type", "application/json");
    xhttp.setRequestHeader("Authorization", "Bearer " + token);
    xhttp.send(JSON.stringify(data));
}
1
  • 1
    IMO you can't do that, use the return type instead, you can also use the promise if needed and get the return value inside the then() of the promise. Dec 17, 2020 at 7:59

1 Answer 1

3

Primitives are passed by value, objects by reference, same as many other languages. As such, changing your copy of showSpinner won't change the caller's version of it. A more useful version of your function would look like this:

async performCallout({method, endpoint, data, token, disableSpinner}) {
    return new Promise((resolve,reject) => {
        if (!data) {
            return;
        }
        let req = new XMLHttpRequest();
        req.onreadystatechange = () => {
            if (req.readyState === 4) {
                // perform 
                disableSpinner && disableSpinner();
                if (req.status < 300) {
                    resolve(req.responseText);
                } else {
                    reject({ status: req.status, error: req.responseText });
                }
            }
        };
        req.open(method, endpoint, true); 
        req.setRequestHeader("Access-Control-Allow-Origin", "*");
        req.setRequestHeader("Content-type", "application/json");
        req.setRequestHeader("Authorization", "Bearer " + token);
        req.send(JSON.stringify(data));
    });
}

This method would allow you to pass in a function to disable the spinner when done:

const disableSpinner = () => { this.showSpinner = false; }
try {
  let result = await performCallout({
    method, endpoint, data, token, disableSpinner
  });
  this.handleSuccess(result);
} catch(ex) {
  this.handleException(ex);
}

But, that's actually pretty silly, I don't see any advantage to doing that as opposed to just disabling the spinner manually when you're done:

try {
  let result = await performCallout({
    method, endpoint, data, token
  });
  this.handleSuccess(result);
} catch(ex) {
  this.handleException(ex);
} finally {
  this.showSpinner = false;
}

Or even:

performCallout({ method, endpoint, data, token })
.then((result) => { this.handleSuccess(result); })
.catch((error) => { this.handleError(error); })
.finally(() => { this.showSpinner = false; });
1
  • 1
    thank you for the different perspectives. Will surely try those :)
    – Ysr Shk
    Dec 17, 2020 at 11:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .