This article shows C# developers the equivalent concepts of asynchronous programming in JavaScript.

Task (C#) vs Promise (JavaScript)

CancellationToken (C#) vs AbortSignal (JavaScript)

CancellationTokenSource (C#) vs AbortController (JavaScript)

TaskCompletionSource (C#) vs Promise (JavaScript)

var tcs = new TaskCompletionSource<DateTime>(); 
var timer = new Timer();
obj.Elapsed += (sender, e) => {
  tcs.SetResult(e.SignalTime);
  timer.Stop();
};
timer.Enabled = true;

await tcs.Task;
// JavaScript
const delay = ms => new Promise((resolve, reject) => {
  setTimeout(resolve, ms);
});

await delay(1_000);

TaskCompletionSource in C# is only used in rare cases (WaitForAppStartup) or legecy code base (e.g. event based API).

async and await in C# and JavaScript

C# and JavaScript share the same syntax using the async and await keywords.

// C#
async Task<string> TestAsync()
{
    return await Task.FromResult("Hello");
}
// JavaScript
async function test() {
  return await Promise.resolve('Hello');
}

await - async vs sync

In C# a Task may execute synchronous. In JavaScript a Promise (even Promise.resolve()) is always executed asynchronous.

.NET 8 / C# added the ability to force a Task to execute asynchronous (pull request).

await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);