Invoke a built-in function that prints "done" to the console after 1 second, without blocking subsequent code.
console.log("before timeout");

// this will take a second:
setTimeout(() => console.log("done"), 1000);

// this will NOT have to wait until the second is over:
console.log("after timeout");

/* output:
before timeout
after timeout
done
*/
Define a Promise that succeeds after 1 second, returning "done".
let p = new Promise((resolve, reject) => { 
        setTimeout(() => resolve("done"), 1000);
});
Invoke the previously defined promise, and log its return value.
let p = new Promise((resolve, reject) => { 
    setTimeout(() => resolve("done"), 1000);
});

console.log("before promise invocation");

// this will take a second:
p.then(promiseReturn => console.log(promiseReturn));

// this will NOT have to wait until the second is over:
console.log("after promise invocation");

/* output:
before promise invocation
after promise invocation
done
*/
"Await" the previously defined promise.
// the "await" keyword used below requires an async function:
async function asyncFunction() {

    let p = new Promise((resolve, reject) => { 
        setTimeout(() => resolve("done"), 1000);
    });

    console.log("before await invocation");

    // this will take a second:
    console.log(await p);

    // this will have to WAIT until the second is over:
    console.log("after await invocation");

}

console.log("before async invocation");
asyncFunction();
console.log("after async invocation");

/* output:
before async invocation
before await invocation
after async invocation
done
after await invocation
*/
Define a Promise that fails after 1 second, returning "failed".
let p = new Promise((resolve, reject) => { 
        setTimeout(() => reject("failed"), 1000);
});
Invoke the previously defined (failing) promise, and log its return value.
let p = new Promise((resolve, reject) => {
    setTimeout(() => reject("failed"), 1000);
});

console.log("before promise invocation")

// this will take a second:
p
    // the "then" function will not be called in case of failure...
    .then(promiseReturn => console.log(promiseReturn))
    // but the "catch" function will:
    .catch(promiseReturn => console.log("caught: " + promiseReturn))

// this will NOT have to wait until the second is over:
console.log("after promise invocation");

/* output:
before promise invocation
after promise invocation
caught: failed
*/
"Await" the previously defined (failing) promise.
// the "await" keyword used below requires an async function:
async function asyncFunction() {

    let p = new Promise((resolve, reject) => { 
        setTimeout(() => reject("failed"), 1000);
    });

    // promise handling with "await" requires try-catch to handle failures:
    try {

        console.log("before await invocation");

        // this will fail after a second (i.e., no output):
        console.log(await p);

        // this will not be invoked at all:
        console.log("after await invocation (success)");

    } catch (promiseReturn) {

        // this will be invoked after 1 second
        console.log(`caught after await invocation: ${promiseReturn}`);
        
    }

}

console.log("before async invocation");
asyncFunction();
console.log("after async invocation");

/* output:
before async invocation
before await invocation
after async invocation
caught after await invocation: failed
*/