async function
should have await
expression JS-0116async
function without any await
expressions191 });
192}
193
194export async function isLoggedIn() {195 return initStaff().then(info => {196 return info.rank > 0;197 });198}199
200export function banSelectedPost() {
201 const boardDirArr = location.pathname.split("/");
async
function without any await
expressions178 });
179}
180
181export async function getPostInfo(id: number):Promise<PostInfo> {182 return $.ajax({183 method: "GET",184 url: `${webroot}manage/postinfo`,185 data: {186 postid: id187 },188 async: true,189 cache: true,190 dataType: "json"191 });192}193
194export async function isLoggedIn() {
195 return initStaff().then(info => {
async
function without any await
expressions143}
144
145
146export async function initStaff() {147 if(staffInfo !== null || staffActions?.length > 0)148 // don't make multiple unnecessary AJAX requests149 return staffInfo;150151 return $.ajax({152 method: "GET",153 url: `${webroot}manage/staffinfo`,154 async: true,155 cache: false,156 dataType: "json",157 success: (result:string|StaffInfo) => {158 if(typeof result === "string") {159 try {160 staffInfo = JSON.parse(result);161 } catch(e) {162 // presumably not logged in163 staffActions = [];164 }165 } else if(typeof result === "object") {166 staffInfo = result;167 }168 staffActions = staffInfo.actions;169 return staffInfo;170 },171 error: (e: JQuery.jqXHR) => {172 console.error("Error getting actions list:", e);173 }174 }).then(() => {175 if(staffInfo.rank > 0)176 setupManagementEvents();177 return staffInfo;178 });179}180
181export async function getPostInfo(id: number):Promise<PostInfo> {
182 return $.ajax({
async
function without any await
expressions 2
3import $ from "jquery";
4
5export async function getThreadJSON(threadID: number, board: string) { 6 return $.ajax({ 7 url: `${webroot}${board}/res/${threadID}.json`, 8 cache: false, 9 dataType: "json",10 });11}
async
function without any await
expressions22 * @param op The post number of the top post in the thread
23 * @param lock If true, the thread will be locked, otherwise it will be unlocked
24 */
25export async function updateThreadLock(board: string, op: number, lock: boolean) {26 const data: BoardLockJSON = {27 board: board,28 thread: op,29 json: 130 };31 if(lock) {32 data.lock = "Not locked";33 } else {34 data.unlock = "Locked";35 }36 $.post({37 url: webroot + "manage/threadattrs",38 data: data39 }).then((_data) => {40 alert("Thread " + (lock?"locked":"unlocked") + " successfully");41 const $lockOpt = $(`select#op${op} option`)42 .filter((_i, el) => el.textContent === "Lock thread" || el.textContent === "Unlock thread");43 if(lock) {44 $(`div#op${op} span.status-icons`).append(45 $("<img/>").attr({46 class: "locked-icon",47 src: webroot + "static/lock.png",48 alt: "Thread locked",49 title: "Thread locked"50 })51 );52 $lockOpt.text("Unlock thread");53 } else {54 $(`div#op${op} img.locked-icon`).remove();55 $lockOpt.text("Lock thread");56 }57 }).catch((data: any, _status: any, xhr: any) => {58 if(data.responseJSON !== undefined && data.responseJSON.message !== undefined) {59 alert(`Error updating thread /${board}/${op} lock status: ${data.responseJSON.message}`);60 } else {61 alert("Unable to send request: " + xhr);62 }63 });64}
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() {}