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();
CodePudding user response:
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 await
s 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
});
CodePudding user response:
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.