const doTaskAsyncWithCallback = (callback) => {
    fakeError = undefined
    //fakeError = 'Fake error forced for testing!'
    console.log("doTaskAsyncWithCallback.callback(): Starting 2 sec timeout")
    setTimeout(() => {
        console.log("doTaskAsyncWithCallback.callback(): 2 sec timeout complete - invoking callback")
        if(fakeError) {
            return  callback(fakeError, undefined)           
        }
        callback(undefined, { msg: 'Completed after 2 seconds', timeout: 2, units: 'seconds' })
    }, 2000) 
}

console.log('*** nothing blocked - 1 ***')

// Create a promise object passing a function with parms resolve and reject
// Differences:
//   - Its an object not a function so you don't need to run it.  runs when instantiated. 
//   - The promise function is executed synchonously on construction
//   - The promise's state is set to pending on construction.  
//   - resolve and reject are themselves functions.  Anynchronously invoke
//     resolve on success, reject on error.
//   - Once the resolve or reject are called, the promise object's state cannot be modified.
//   - Subsequent calls to resolve or reject have no effect.
//   - After resolve or reject is called, it's state changes from pending to fullfilled or 
//     rejected respectively.
const taskPromise = new Promise((resolve, reject) => {
    fakeError = undefined
    //fakeError = 'Fake error forced for testing!'
    console.log("doTaskPromise(): Starting 2 sec timeout")
    setTimeout(() => {
        console.log("doTaskPromise(): 2 sec timeout complete - invoking callback")
        if(!fakeError) {
            resolve({ msg: 'Completed after 2 seconds', timeout: 2, units: 'seconds' })
        } else {
            reject(fakeError)
        }
    }, 2000) 
})

console.log('*** nothing blocked - 2 ***')

// Use the callback pattern
doTaskAsyncWithCallback((error, msg) => {
    console.log('anonymousFn(): Callback visited')
    if(error) {
        return console.log('anonymousFn(): Error of some kind occurred.  Error:', error)
    }
    console.log('anonymousFn(): msg: ', msg)
    console.log('anonymousFn(): Callback completed')
})

console.log('*** nothing blocked - 3 ***')

// .then() - registers a callback to be invoked (via resolve) on successful completion of async task.
// .error() = registers a callback to be invoked (via resolve) on successful completion of async task.
taskPromise.then((msg) => {
    console.log('taskPromise.then(): resolve callback visited')
    console.log('taskPromise.then(): msg: ', msg)
    console.log('taskPromise.then(): - resolve callback completed')
}).catch((error) => {
    console.log('taskPromise.catch(): Error of some kind occurred.  Error:', error)
})

console.log('*** nothing blocked - 4 ***')
console.log("*** end of main function ***")
