Skip to content

Javascript Promises are not executed in the correct order

I have a problem. I am trying to do the following:
I first check the url for a containing agentId parameter. Then I want to check in my database if the given agentId belongs to a valid agent. If so, then I want to store the entire object of that agent in a variable called selectedAgent. Then I want to use the selectedAgent in my next 2 functions.

The problem is that it gives me the error: Uncaught TypeError: Cannot read property 'active' of null on line 106. This is caused by the fact that the last function in the chain gets executed before the rest. Here is the code:

const urlString = window.location.search;
const urlParams = new URLSearchParams(urlString);
let selectedAgentId = urlParams.get('agentId');
let selectedAgent = null;


document.addEventListener('DOMContentLoaded', function(event) {

    getStartupAgentData().then(fillAgentComboBox()).then(setToggleButtonContent());

});


function getStartupAgentData() {

    return new Promise(function(resolve, reject) {
        $.ajax({
            type: 'POST',
            url: 'overview_get_agent_ajax.php',
            data: 'agentid=' + selectedAgentId, 
            dataType: 'text', 
            success: function(data) {
                selectedAgent = JSON.parse(data)[0];
                console.log(selectedAgent);
                resolve(true);
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                console.log("Failed receiving agents")
                reject(true);
            }
        });
    });

}


function fillAgentComboBox() {

    console.log(selectedAgent);

    return new Promise(function(resolve, reject) {
        getAllAgentData().then(function(agents) {
            
            let comboBoxAgent = document.getElementById("comboBoxAgent");

            for (let i = 0; i < agents.length; i++) {
                let option = document.createElement("option");
                
                // Agent data
                let id = agents[i].id;
                let owner = agents[i].owner;
                let exchange = agents[i].exchange;
                let remark = agents[i].remark;

                let text = "Agent " + id.toString().padStart(4, "0") + " - " + owner + " - " + exchange + " - " + remark;
                option.text = text;
                option.value = id;
                comboBoxAgent.add(option);

                if (selectedAgent === null) {
                    option.selected = true;
                    selectedAgent = agents[i];
                }
                else if (id === selectedAgentId) {
                    option.selected = true;
                    selectedAgent = agents[i];
                }
            }

            // Add agent id to url for other javascripts
            window.history.replaceState(null, null, "?agentId=" + selectedAgent.id);

            resolve(true);

        });

    });

}


function getAllAgentData() {

    return new Promise(function(resolve, reject) {
        $.ajax({
            type: 'POST',
            url: 'overview_get_agents_ajax.php',
            data: '', 
            dataType: 'text', 
            success: function(data) {
                resolve(JSON.parse(data));
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                reject(true);
            }
        });
    });

}


function setToggleButtonContent() {

    let btnToggleAgent = document.getElementById("btnToggleAgent");

    if (selectedAgent.active == true) {
        btnToggleAgent.style.background = "#EE4141";
        btnToggleAgent.innerHTML = "Stop";
    }
    else {
        btnToggleAgent.style.background = "#44B642";
        btnToggleAgent.innerHTML = "Start";
    }

}

This is the error I get: enter image description here

How can I fix this?

Answer

You want then(fillAgentComboBox) without the () which is calling your function in place and kicking it off immediately. You could also do then(() => fillAgentComboBox())