0

I have just come across an anonymous self-invoking JavaScript function and am unsure as to what the point is. I have read a couple of posts about how it is to do with scope, but it still doesn't make total sense to me.

The example in question:

const express = require("express");
const axios = require("axios");
const redis = require("redis");

const app = express();
const port = process.env.PORT || 3000;

let redisClient;

(async () => {
  redisClient = redis.createClient();

  redisClient.on("error", (error) => console.error(`Error : ${error}`));

  await redisClient.connect();
})();

async function fetchApiData(species) {
  ...
}
...

What is the difference between this

let redisClient;

(async () => {
  redisClient = redis.createClient();

  redisClient.on("error", (error) => console.error(`Error : ${error}`));

  await redisClient.connect();
})();

and just doing the following

let redisClient;
redisClient = redis.createClient();
redisClient.on("error", (error) => console.error(`Error : ${error}`));
await redisClient.connect();
Barmar
  • 741,623
  • 53
  • 500
  • 612
HubertBlu
  • 747
  • 1
  • 7
  • 20
  • 4
    You can't use `await` outside an async function. The IIFE is async to allow this. – Barmar Sep 08 '22 at 23:52
  • It did just occur to me that you cant use await outside an async function but I thought there might be more to it. Thanks! – HubertBlu Sep 08 '22 at 23:53
  • Note that it is possible to use `await` outside of an `async` function if your module is an ES6 module. – Nick Parsons Sep 08 '22 at 23:56
  • 1
    Does this answer your question? [What is the purpose of a self executing function in javascript?](https://stackoverflow.com/questions/592396/what-is-the-purpose-of-a-self-executing-function-in-javascript) – jmargolisvt Sep 08 '22 at 23:57
  • Sure it awaits `connect()` but nothing triggers afterwards. There is no point in using the await, which means you don’t need an async iife either. – James Sep 09 '22 at 00:03

2 Answers2

1

The reason you can't do

let redisClient;
redisClient = redis.createClient();
redisClient.on("error", (error) => console.error(`Error : ${error}`));
await redisClient.connect();

is that you can't await on the top level - in the CommonJS module system. It's possible in ESM, but not in Node's default CommonJS.

That said, the original code does look pretty odd. It looks like it was written by someone who may not have known how to turn await into a .then - an async IIFE like that that only awaits a single Promise seems odd, especially since there's nothing that comes after the await in the IIFE. The original code is effectively the same as

const redisClient = redis.createClient();
redisClient.on("error", (error) => console.error(`Error : ${error}`));
redisClient.connect(); // dangling Promise

The original code creates a dangling Promise too, because the Promise returned by the IIFE isn't caught. In both codes, it would be better to .catch the possible rejection of the .connect call. (Possible unhandled rejections should always be avoided - even if there's also an error listener on redisClient.)

const redisClient = redis.createClient();
redisClient.on("error", (error) => console.error(`Error : ${error}`));
redisClient.connect()
  .catch((error) => {
    // either do error handling here, or simply do nothing
    // if the error handler above is sufficient
    // but don't leave this `.catch` out
  });
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

You can't use await outside of a function -- this is called "top-level await". Yes, browser DevTools will let you do that in their JS consoles, but regular scripts cannot in either browsers or the Node environment.

So, the difference between sample A and sample B is that sample B will not work and sample A will.

Tom
  • 8,509
  • 7
  • 49
  • 78
  • 2
    On the other hand, if `await` is only used at the end of the function, there's not much point to it. So this is a poor example. – Barmar Sep 08 '22 at 23:54
  • 1
    I suspect the author of the code thought that the code after the IIFE would wait for the IIFE to finish. – Barmar Sep 08 '22 at 23:55