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();
2
Answers
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.
The reason you can’t do
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 onlyawait
s a single Promise seems odd, especially since there’s nothing that comes after theawait
in the IIFE. The original code is effectively the same asThe 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 onredisClient
.)