async
function without any await
expressions170 * @param text - Stringified text to sent as code to be executed inside Nuke.
171 * @param timeout - time for the timeout connection. Defaults to 10000 ms (10sec).
172 */
173export async function sendData(174 host: string,175 port: number,176 text: string,177 timeout = 10000178): Promise<{ message: string; error: boolean; errorMessage: string }> {179 return new Promise((resolve, reject) => {180 const client = new Socket();181 const status = {182 message: "",183 error: false,184 errorMessage: "",185 };186187 logDebugNetwork(`Try connecting to ${host}:${port}`);188189 /**190 * Set connection timeout.191 *192 * Once emitted will close the socket with an error: 'connection timeout'.193 */194 client.setTimeout(timeout, () => {195 logDebugNetwork("Connection timeout.");196 client.destroy(new Error("Connection timeout"));197 reject(status);198 });199200 try {201 /**202 * Initiate a connection on a given socket.203 *204 * If host is undefined, will fallback to localhost.205 */206 client.connect(port, host, function () {207 logDebugNetwork("Connected.");208 client.write(text);209 });210 } catch (error) {211 if (error instanceof RangeError) {212 const msg = `Port is out of range. Value should be >= 49567 and < 65536. Received: ${port}`;213 logDebugNetwork(msg);214 client.destroy(new Error("Port out of range"));215 status.errorMessage = "Port is out of range";216 } else {217 const msg = `Unknown exception. ${String(error)}`;218 logDebugNetwork(msg);219 client.destroy(new Error(msg));220 status.errorMessage = msg;221 }222 status.error = true;223 reject(status);224 }225226 /**227 * Emitted when data is received.228 *229 * The argument data will be a Buffer or String. Encoding of data is set by socket.setEncoding().230 */231 client.on("data", function (data: string | Buffer) {232 const textData = data.toString();233234 const oneLineData = textData.replace(/\n/g, "\\n");235 logDebugNetwork(`Received: "${oneLineData}"\n`);236237 const filePath = JSON.parse(text)["file"];238 writeToOutputWindow(textData, filePath);239240 status.message = data.toString().trim();241 resolve(status);242 client.end();243 });244245 /**246 * Emitted after resolving the host name but before connecting.247 */248 client.on(249 "lookup",250 function (error: Error | null, address: string, family: string, host: string) {251 logDebugNetwork(252 "Socket Lookup :: " +253 JSON.stringify({ address, family, host, error }, null, " ")254 );255256 if (error) {257 logDebugNetwork(`${error.message}`);258 status.errorMessage = error.message;259 reject(status);260 }261262 }263 );264265 /**266 * Emitted when an error occurs.267 *268 * The 'close' event will be called directly following this event.269 */270 client.on("error", function (error: Error) {271 const msg = `272 Couldn't connect to NukeServerSocket. Check the plugin and try again. 273 If manual connection is enable, verify that the port and host address are correct. 274 ${error.message}`;275 vscode.window.showErrorMessage(msg);276277 status.errorMessage = "Connection refused";278 status.error = true;279 reject(status);280 });281282 /**283 * Emitted when a socket is ready to be used.284 *285 * Triggered immediately after 'connect'.286 */287 client.on("ready", function () {288 logDebugNetwork("Message ready.");289 });290291 /**292 * Emitted once the socket is fully closed.293 */294 client.on("close", function (hadError: boolean) {295 logDebugNetwork(`Connection closed. Had Errors: ${hadError.toString()}`);296 });297298 /**299 * Emitted when the other end of the socket signals the end of transmission.300 */301 client.on("end", function () {302 logDebugNetwork("Connection ended.");303 });304305 });306}307
308/**
309 * Prepare a debug message to send to the socket.
async
function without any await
expressions22 return [];
23 }
24
25 private async getAllNodes(): Promise<vscode.CompletionItem[]> {26 return askNuke("[n.name() for n in nuke.allNodes()]").then((data) => {27 const nodes = JSON.parse(data.message.replace(/'/g, '"'));2829 const items: vscode.CompletionItem[] = [];30 for (const node of nodes) {31 items.push(new vscode.CompletionItem(`"${node}"`, vscode.CompletionItemKind.Class));32 }33 return items;34 });35 }36}
async
function without any await
expressions 2
3import { sendCommand } from "../socket";
4
5async function askNuke(text: string) { 6 return sendCommand(JSON.stringify({ text: text, file: "" })); 7} 8
9export class NukeCompletionProvider implements vscode.CompletionItemProvider {
10 provideCompletionItems(
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:
- The return value is always a
Promise
. - You can use the
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.
Bad Practice
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") });
Recommended
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() {}