Difference between Javascript async functions and Web workers?

后端 未结 6 1560
南笙
南笙 2021-02-05 06:53

Threading-wise, what\'s the difference between web workers and functions declared as

async function xxx()
{
}

?

I am aware web worker

6条回答
  •  猫巷女王i
    2021-02-05 07:34

    async functions are just syntactic sugar around Promises and they are wrappers for callbacks.

    // v await is just syntactic sugar
    //                 v Promises are just wrappers
    //                                         v functions taking callbacks are actually the source for the asynchronous behavior
       await new Promise(resolve => setTimeout(resolve));
    

    Now a callback could be called back immediately by the code, e.g. if you .filter an array, or the engine could store the callback internally somewhere. Then, when a specific event occurs, it executes the callback. One could say that these are asynchronous callbacks, and those are usually the ones we wrap into Promises and await them.

    To make sure that two callbacks do not run at the same time (which would make concurrent modifications possible, which causes a lot of trouble) whenever an event occurs the event does not get processed immediately, instead a task (callback with arguments) gets placed into a task queue. Whenever the JavaScript agent (= thread) finishes execution of the current task, it looks into that queue for the next task to process¹.

    Therefore one could say that an async function is just a way to express a continuous series of tasks.

     async function getPage() {
       // the first task starts fetching the webpage
       const response = await fetch("https://stackoverflow.com"); // callback gets registered under the hood somewhere, somewhen an event gets triggered
       // the second task starts parsing the content
       const result = await response.json(); // again, callback and event under the hood
       // the third task logs the result
       console.log(result);
    }
    
    // the same series of tasks can also be found here:
    fetch("https://stackoverflow.com") // first task
       .then(response => response.json()) // second task / callback
       .then(result => console.log(result)); // third task / callback
    

    Although two tasks cannot run in parallel on one agent (= thread), the task of one async function might run between the tasks of another. Therefore, two async functions can run concurrently.

    Now who does produce these asynchronous events? That depends on what you are awaiting in the async function (or rather: what callback you registered). If it is a timer (setTimeout), an internal timer is set and the JS-thread continues with other tasks until the timer is done and then it executes the callback passed. Some of them, especially in the Node.js environment (fetch, fs.readFile) will start another thread internally. You only hand over some arguments and receive the results when the thread is done (through an event).

    To get real parallelism, that is running two tasks at the same time, multiple agents are needed. WebWorkers are exactly that - agents. The code in the WebWorker therefore runs independently (has it's own task queues and executor).

    Agents can communicate with each other via events, and you can react to those events with callbacks. For sure you can await actions from another agent too, if you wrap the callbacks into Promises:

    const workerDone = new Promise(res => window.onmessage = res);
    
    (async function(){
        const result = await workerDone;
            //...
    })();
    

    TL;DR:

    JS  <---> callbacks / promises <--> internal Thread / Webworker
    

    ¹ There are other terms coined for this behavior, such as event loop / queue and others. The term task is specified by ECMA262.

提交回复
热议问题