0

I have the following private JavaScript function inside a module that represents a username object. Whenever I call the function, it always returns false no matter what the result of the fetch is. I'm new to JavaScript, fetches, and promises so there's something I'm not understanding that I haven't been able to figure out.

const Username = (function () {

    const username = document.getElementById('id_username');
    const usernameError = document.querySelector('#id_username + span.error');

    function _isBlank() {
        if (username.value === '') {
            usernameError.textContent = "Username is required.";
            usernameError.className = 'error active';
            return true;
        } else {
            usernameError.innerHTML = '';
            usernameError.className = 'error';
            return false;
        }
    }

    function _isAvailable() {
        fetch(`http://127.0.0.1:8000/users/${username.value}`)
            .then(res => res.text())
            .then(data => {
                if (!data.includes('username_available')) {          // Condition fails...
                    console.log("Username is not available");
                    showError('That username is not available. Try another.');
                    return false;
                } else {
                    console.log("Username is available");            // And execution continues here
                    hideError();
                    return true;
                }
            })
            .catch(err => console.log("Error: " + err));
    }

    function _isValid() {
        let is_blank = _isBlank();
        let is_available = _isAvailable();              // Returns false even if username is available
        // if (!_isBlank() && _isAvailable()) {
        if (!is_blank && is_available) {
            return true;                                // This should get set but it doesn't
        } else {
            return false;
        }
    }

    function hideError() {
        ...
    }

    function showError(message) {
        ...
    }

    // Public vars and functions
    return {
        isValid: _isValid,
    };

})();

When I examine what's happening in the Chrome debugger, I see that the is_available variable is always set to false by the private _isAvailable function. In the latter function, if I execute the fetch against my API endpoint with a username that I know is not in my database (i.e, it's an available username) and I examine the data variable, it contains this expected result:

"["result": "username available"]"

Execution then continues in the else block to indicate that the username is available and I try to return true. But, as I've said, the ```is_available`` variable is still being set to false when I know I just returned true. Am I making a mistake in how I've written the fetch function?

Jim
  • 13,430
  • 26
  • 104
  • 155
  • 1
    `fetch()` is asynchronous. – Barmar Jun 29 '20 at 22:53
  • 1
    See https://javascript.info/promise-chaining – PM 77-1 Jun 29 '20 at 22:57
  • Like @Barmar stated, but even so, you couldn't `return` something in `_isAvailable` from a nested Anonymous function like that anyways. That would just return to where the Anonymous function is executed. – StackSlave Jun 29 '20 at 23:07
  • That's what I don't get. How do you return a value from _isAvailable based on what happens with the fetch? – Jim Jun 29 '20 at 23:17
  • 1
    @Ray You don't. You either pass a callback to the function and call it in the `.then()` method, you return the promise from the function and then use `.then()` in the caller, or you use `async` and `await`. All this is explained in the duplicate question. – Barmar Jun 29 '20 at 23:36

0 Answers0