async function
should have await
expression JS-0116async
function without any await
expressions 62 }
63 };
64
65 const handleBulkMail = async (type: EmailType) => { 66 if (data !== null) { 67 const users = data?.data.users as ManagedUser[]; 68 if (type === 'reminder') { 69 for (const user of users) { 70 handleMail(user.first_name, user.email, type); 71 } 72 } else { 73 for (const user of users) { 74 handleMail( 75 user.first_name, 76 user.email, 77 type, 78 user.id, 79 queryParams.get('status') === 'True' ? 'False' : 'True' 80 ); 81 } 82 } 83 } 84 }; 85
86 interface ManagedUser {
87 id: number;
async
function without any await
expressions 12// this is documented somewhere in the github discussion of vercel;
13// when using vite with vercel serverless, use the require syntax
14
15const sendEmail = async ( 16 req: VercelRequest, 17 devMode: boolean, 18 res: VercelResponse, 19 emailT: EmailType 20) => { 21 const { firstName, email } = req.body; 22 let templateId; 23 switch (emailT) { 24 case 'welcome': 25 templateId = process.env.SENDGRID_WELCOME_TID; 26 break; 27 case 'reminder': 28 templateId = process.env.SENDGRID_REMINDER_TID; 29 break; 30 case 'approved': 31 templateId = process.env.SENDGRID_APPROVED_TID; 32 break; 33 default: 34 templateId = process.env.SENDGRID_WELCOME_TID; 35 } 36 const message = { 37 to: devMode ? '[email protected]' : email, 38 from: 'Arth from DevClad<[email protected]>', 39 template_id: templateId, 40 dynamic_template_data: { 41 firstName, 42 }, 43 }; 44 sgMail 45 .send(message) 46 .then(() => { 47 res.status(200).json({ 48 message: 'Email sent successfully', 49 }); 50 }) 51 .catch((error: unknown) => { 52 res.status(400).json({ message: 'Email not sent', error }); 53 }); 54}; 55
56const verifyToken = async (token: string): Promise<boolean> => {
57 const apiURL = process.env.VITE_API_URL;
async
function without any await
expressions22 return null;
23};
24
25export const getUsers = async (token: string, filter?: string) => {26 let url;27 if (filter) {28 url = `${API_URL}/internal/users?status=${filter}`;29 } else {30 url = `${API_URL}/internal/users`;31 }32 if (checkTokenType(token)) {33 return axios({34 method: 'GET',35 url,36 headers: {37 Authorization: `Bearer ${token}`,38 'Content-Type': 'application/json',39 Accept: 'application/json',40 },41 });42 }43 return null;44};45
46export const adminQuery = (token: string, qc: QueryClient) => ({
47 queryKey: ['admin'],
async
function without any await
expressions160 return null;
161}
162
163export async function verifyToken(token: string, queryClient?: QueryClient): Promise<boolean> {164 const url = `${API_URL}/auth/token/verify/`;165 return axios({166 method: 'POST',167 url,168 data: { token },169 headers: { 'Content-Type': 'application/json' },170 })171 .then((resp) => {172 if (resp.status === 200) {173 return true;174 }175 return false;176 })177 .catch(() => {178 // case: token expired on the server but not on client179 if (queryClient) {180 refreshToken(queryClient);181 }182 return false;183 });184}185
186export async function getUser(token: string, queryClient?: QueryClient) {
187 const url = `${API_URL}/auth/user/`;
async
function without any await
expressions218 return null;
219}
220
221export async function SignUp(user: NewUser) {222 return axios223 .post(`${API_URL}/auth/registration/`, {224 first_name: user.firstName,225 last_name: user.lastName,226 email: user.email,227 password1: user.password1,228 password2: user.password2,229 headers,230 })231 .then((resp) => resp)232 .catch((err) => err);233}234
235export async function logIn(queryClient: QueryClient, email: string, password: string) {
236 const url = `${API_URL}/auth/login/`;
A function that does not contain any await
expressions should not be async
(except for some edge cases
in TypeScript which are discussed below).
Asynchronous functions in JavaScript behave differently than other functions in two important ways:
Promise
.await
operator inside them.Functions are made async
so that we can use the await
operator inside them.
Consider this example:
async function fetchData(processDataItem) {
const response = await fetch(DATA_URL);
const data = await response.json();
return data.map(processDataItem);
}
Asynchronous functions that don't use await
might be an unintentional result of refactoring.
Note: This issue ignores async generator functions.
Generators yield
rather than return
a value and async
generators might yield all the values of another async generator without ever actually needing to use await
.
In TypeScript, one might feel the need to make a function async
to comply with type signatures defined by an interface.
Ideally, the code should be refactored to get rid of such restrictions, but sometimes that isn't feasible
(For example, when we are implementing an interface defined in a 3rd party library like Next.js).
This situation can easily be circumvented by returning the value with a call to Promise.resolve
:
interface HasAsyncFunc {
getNum: () => Promise<number>
}
// Not recommended:
const o: HasAsyncFunc = {
async getNum() { return 1 }
}
// Recommended:
const o: HasAsyncFunc = {
// We only use `Promise.resolve` to adhere to the type
// of the surrounding object.
getNum() { return Promise.resolve(1) }
}
It is also advised to add a comment near the redundant promise to make the intent clear.
async function fetchData(): string {
// `readFileSync` is a synchronous function that blocks
// the main thread, and thus does not need to be `await`ed
return fs.readFileSync("data.txt", "utf-8");
}
performAction(async () => { console.log("no awaits in here") });
async function fetchDataAsync(): Promise<string> {
return await fs.readFile("data.txt", "utf-8")
}
performAction(async () => { await writeToFile(data) });
// Allow empty functions.
async function no_op() {}