U8 main function and async calls


Usually, when u8 some_file.js is invoked, the file is first interpreted and executed, then, if main(args) is found, it is called with arguments passed to the command line past the file name. For example, suppose we have a script:

// main.js

console.log("main started");

function main(args) {
    console.log("main called with args=["+args.join(',')+"]");
    return 0;
}

and we will run it as:

u8 main.js foo bar buzz

we'll get the following output:

testmain started
main called with args=[foo,bar,buzz]

as you can see, first the script is interpreted as is, then the main function is found and executed.

The value returned by main function, will be passed out as process exit code, unless the background mode is used (see below).

Asynchronous operations

As long as the main script is simple and needs no async operations, it could just run and return control from main. In fact, usually it is much more complex and may contain some file IO, network IO, timer scheduling or any other asynchronous operations.

Now the program should wait until all your operations will be completed, so if you just exit the main() the process will immediately be terminated and possible pending async procedures will not be called. For example, suppose we run:

console.log("main started");

async function someIoOperation() {
    await sleep(200);
    console.log("async processed");
}

function main(args) { // ERROR
    someIoOperation();
    return 0;
}

we got only main started and the process terminates without waiting for someOperation() to complete. Sure, the system just has no idea whether ot not to wait for anything else, so the program need to inform the U8 it has some async tasks in progress to wait for. It could be done in 2 simple ways.

Async main

The solution is as simple as making async main():

console.log("main started");

async function someIoOperation() {
    await sleep(200);
    console.log("async processed");
    return 0; // this will be am exit status
}

async function main(args) {
    await someIoOperation();
}

That simple. If main() return Promise, what async function always does, the U8 will wait for the promise to be resolved and use the result as an exit code, which therefore should be an integer.

If the promise returned by the main is be rejected, the reason and stack (if any) will be printed to the console.error() and the process will be terminated with exit code 1000.

Premature exit with async main

In the emergency case is it possible to cancel execution calling exit(intCode);. It will not exit immediately but will finish all pending callbacks. Still we strongly recommend to design your application with care and use a promise in main function to exit application.

Deprecated and unsupported features

waitExit() is no more used. Use async main() instead.