Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 11, 2022 11:06 am GMT

Understanding Javascript Async Race Conditions

The term "race condition" is usually applied to the conflict in accessing shared variables in a multi-threading environment. In Javascript, your JS code is executed only by a single thread at a time, but it's still possible to create similar issues.

This is a common problem when people are just blindly making their functions async, without thinking about the consequences.

Let's take a very simple example - lazy-loading some kind of single-instance resource.

The synchronous version is simple:

let res;function get_resource() {    if(!res) res = init_resource();    return res;}

Asynchronous version:

let res;async function get_resource() {    if(!res) res = await init_resource();    return res;}

Imagine get_resource() being called in a web server, on every request. If enough time passes between the first and the second request, everything will work fine. But what happens if you get more requests, while the first one is still waiting for the resource?

This can lead to serious problems that are very hard to debug.

More examples

Here are some examples (from this HN thread):

Account balance:

    async function deduct(amt) {        var balance = await getBalance();        if (balance >= amt)            return await setBalance(balance - amt);    }

And more subtle example:

  async function totalSize(fol) {    const files = await fol.getFiles();    let totalSize = 0;    await Promise.all(files.map(async file => {      totalSize += await file.getSize();    }));    // totalSize is now way too small    return totalSize;  }

Possible solutions

The best way to avoid these types of problems is to avoid async functions where it's not absolutely necessary (see: [[Functional core, imperative shell]]).

If it's not possible, you may want to consider using Mutex (from Mutual Exclusion) - once someone acquires the lock, other requests will be blocked, until the original holder release the lock.

i.e. with async-mutex package our previous example may look like this:

let res;async function get_resource() {    await mutex.runExclusive(async () => {        if(!res) res = await init_resource();    });    return res;}

async-mutex has also support for semaphores - it's a similar concept, but multiple locks can be acquired.

Note: this is a snapshot of (WIP) topic from the Understanding Simplicity wiki. All suggestions (and reactions) are welcome. You can find the latest version here: Understanding Javascript Async Race Conditions


Original Link: https://dev.to/devsimplicity/understanding-javascript-async-race-conditions-19oh

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To