Search code examples
javascriptasynchronouscallbacksettimeout

JavaScript callback functions only partially execute


I am attempting to create a program illustrating nested callback functions in JavaScript, without promises or asyc/await. Each function should console its execution number and calculate the next execution number to be passed up to its predecessor. However, when calling the sequenceLogs function, only logFirst is executed. The other functions are never executed. How do I get the second through fifth functions to execute properly?

function logFirst(number) {
    console.log(`Runs ${number}rst`);
    return;
}
function logSecond(number) {
    console.log(`Runs ${number}nd`);
    let newNumber;
    setTimeout(() => {newNumber = number - 1;}, 75);
    return newNumber;
}
function logThird(number) {
    console.log(`Runs ${number}rd`);
    return number-1;
}
function logFourth(number) {
    console.log(`Runs ${number}th`);
    let newNumber; 
    setTimeout(() => {newNumber = number - 1;}, 50);
    return newNumber;
}
function logFifth(number) {
    console.log(`Runs ${number}th`);
    return number-1;   
}

const sequenceLogs = (number) => {
    return logFirst(() => {
        logSecond(()=>{
            logThird(()=> {
                logFourth(()=>{
                    logFifth(number);
                });
            });
        });
    });
};

// Set the number to run in the fifth function
sequenceLogs(5);


Solution

  • Please see solution below:

    // log function
    function logData(number, suffix, time, retrieveDataCB) {
      // console out the current number
      console.log(`Runs ${number}` + suffix);
    
      setTimeout(() => {
        console.log("Now we have the data");
        // instead of returning the data before
        // it's available, wrap the data to be
        // returned in a callback, so it will have
        // access in the main execution loop
    
        // once setTimeout runs, we invoke the
        // retrieveDataCB function, which triggers
        // gives the main loop access to the data.
    
        retrieveDataCB({ newNumber: number + 1 });
      }, time);
    
      // Runs before data is available.
      // return number + 1;
    }
    
    //Run the sequence
    const executeMainLoop = (startingNum) => {
      // Execute getNumber function and pass the retrieveDataCB, which will have access to the newNumber object.
      logData(startingNum, "rst", 0, (data) => {
        // console.log("NewNumber2:", data.newNumber);
        // log 2nd stmt
        logData(data.newNumber, "nd", 5000, (data) => {
          // log 3rd stmt
          logData(data.newNumber, "rd", 0, (data) => {
            // log 4th stmt
            logData(data.newNumber, "th", 50, (data) => {
              // log 5th stmt
              logData(data.newNumber, "th", 0, (data) => {});
            });
          });
        });
      });
    };
    
    //   run sequence function
    executeMainLoop(1);