Notes about Javascript asynchronous programming.
1. My examples
I without haste try to prepare to lecture about Asynchronous programing with Javascript, this is base of my code to that lecture:
- Async
- Async Await
- Async Timeout
- Async Promise
- Image Async
- Async Classes
- Async Closure
- Async Concurrency
- Async Dom Manipulation
- Node Async
- Async Node EventEmitter
- Async Sockets
- Browser Async EventHandling
- Observable
2. Two main mistakes in JS Async.
But, without doubt, number one issue in any JS code is forEach Doesn't Work with Async/Await. Something like this y.ForEach (async x => await { .. }}).
The forEach method doesn't wait for asynchronous operations within its callback to complete before moving to the next iteration. This means that if you have an await inside the forEach callback, the loop will continue iterating without waiting for the await to resolve. The return 'OK' statement will execute before any of the asynchronous operations inside the loop have finished.
Therefore each => async callback in ForEach must be refactored by one of two ways:
- The for...of loop iterates over iterable objects (like arrays). Crucially, it waits for each await to complete before proceeding to the next iteration.
- 2. Promise.all (for Parallel Execution). If the calls to Y are independent and can be executed in parallel (which can be much faster), use Promise.all:
1: async function X() {
2: for (const item of data.entries) { // Use for...of
3: await Y(item); // Wait for each call to Y to complete
4: }
5: return 'OK'; // Return only after all items are processed
6: }
1: async function X() {
2: await Promise.all(data.entries.map(async (item) => {
3: await Y(item);
4: }));
5:
6: return 'OK'; // Return after all Promises in the array have resolved
7: }
Promise.all takes an array of Promises. It waits for all of them to resolve (or for any one of them to reject). This allows the calls to Y(item) to run concurrently, improving performance if they don't depend on each other.
Second main mistake with Async/Await is unexpected transformation continue to break. If an await is present inside a for...of loop before the continue statement is reached, continue will effectively behave like a break in your scenario.
The continue keyword is designed to immediately jump to the next iteration of the loop. However, when you have an await within the loop, the execution flow changes. The await effectively splits the loop's logic into two parts:
- Before the await: This part executes synchronously.
- After the await: This part executes asynchronously when the awaited Promise resolves.
If the continue is in the asynchronous part of the loop (after an await), it won't behave as expected. It will effectively stop the execution of that asynchronous part and act as a break, because the loop is no longer in a state to "continue" synchronously to the next iteration; that flow of control has already been handed over to the asynchronous mechanism.
1: async function processData(data) {
2: for (const x of data) {
3: await someAsyncOperation(x); // Asynchronous operation
4: if (someCondition(x)) {
5: continue; // This will act like a break because it's after the await
6: }
7: // ... rest of the code that won't be reached if continue is hit ...
8: }
9: }
To achieve the true continue behavior (skip the rest of the current iteration and go to the next iteration), you must ensure that the continue statement is before any await calls within the loop body:
1: async function processData(data) {
2: for (const x of data) {
3: if (someCondition(x)) {
4: continue; // Correct placement: Before the await
5: }
6: await someAsyncOperation(x); // Asynchronous operation
7:
8: // ... rest of the code that WILL be skipped if continue is hit,
9: // and execution will jump to the next iteration of the for...of loop.
10: }
11: }
By placing the continue before the await, you ensure that it executes synchronously within the loop's normal flow, and it will correctly skip the rest of the current iteration and jump to the next one as intended. This is a crucial distinction when working with async/await within loops. If the condition you are checking requires the results from the async operation, then you will need to structure your code so that you await first, and store the result, and then use an if...else block to conditionally execute the remaining code. In those cases you cannot use continue. You could still move the rest of the code to a separate function and call that function only in the else block. This keeps the for...of loop body smaller and focused on the logic of iteration, delegating the secondary processing to a helper function.
Sorry, I have no time, page will publish soon.
ES6 context:
Task context:
Asynchronous programming in Javascript:
- (2024) Notes about Javascript asynchronous programming #Task
- (2024) Example of my async Angular code (async chain with Fetch site icon plus async save to storage) with ActivityIndicator on frontend #Task
- (2022) RxJs learning conspectus #FrontLearning #Task
- (2022) RxJs animation #Task
My best multithreading/asynchronous programs (.NET) My multithreading experience:
- (2023) Asynchronous MultiThreaded performance test of Confluent Kafka (Net Core 6) #Cloud #Task #WinDesktop
- (2022) Asynchronous MultiThreaded SSH engine for Web (Net Core 6, Linux) - Part 1,2 (Database and SSH client) StreamReader/ReadToEndAsync, Extension/Inherits/Overloads, BeginExecute/EndExecute/IAsyncResult/IProgress(Of T)/Async/Await/CancellationToken/Task.Run/Thread.Yield. #Task #NetCoreBackend #Linux #Yield
- (2022) Asynchronous MultiThreaded SSH engine for Web (Net Core 6, Linux) - Part 3,4 (CryptoAPI/CryptoService and Database Access). Protect password in DB and config, Task.Run for Async DB access, Expand POCO classes, Service lifetime list, Linq and Iterator/Yield functions. #Task #NetCoreBackend #Linux #Yield
- (2022) Asynchronous MultiThreaded SSH engine for Web (Net Core 6, Linux) - Part 5,6 (Crypt/Encrypt JWT Auth header, Middleware, User scoped service, custom AU attribute, custom HttpClient and Typed SignalRHub with saving ConnectionID to Singleton service). #Task #NetCoreBackend #Linux
- (2022) Asynchronous MultiThreaded SSH engine for Web (Net Core 6, Linux) - Part 7,8 (QuartzService/Jobs and Singleton CacheService). ConcurrentDictionary, Interlocked.Increment, SyncLock, Closure variable for MultiThreading, Cron Configuration. #Task #NetCoreBackend #Linux #Kvm
- (2022) Asynchronous MultiThreaded SSH engine for Web (Net Core 6, Linux) - Part 9,10 (BackendAPI for NotificationController and my technique to testing this engine with xUnit). #Task #NetCoreBackend #Linux #Kvm
- (2022) Monitoring docker events #Docker #NodeBackend #Task
- (2022) EventLogger - example of Task.Factory.FromAsync, Task.Run, ReaderWriterLock, Interlocked.Increment, Stream.BeginWrite, SyncLock, Timeout, AsyncCallback, IAsyncResult, String.Format, Timespan.
- (2022) EventLogger - example of Task.Factory.FromAsync, Task.Run, ReaderWriterLock, Interlocked.Increment, Stream.BeginWrite, SyncLock, Timeout, AsyncCallback, IAsyncResult, String.Format, Timespan. #WinDesktop #Task
- (2022) Windows timers investigation (API Timer, Stopwatch Timer, Multimedia Timer). #WinDesktop #TimeSchedule #Task
- (2022) About connection with EF Core and Pomelo provider for MySQL (GetProcessList, EF Core connection count, Setup Max MySQL Connection count. Separate connection for Attributes, Calculate connection for API). #EfCodeFirst #Task
- (2022) About connection with EF Core and Pomelo provider for MySQL (GetProcessList, EF Core connection count, Setup Max MySQL Connection count. Separate connection for Attributes, Calculate connection for API). #EfCodeFirst #Task
- (2019) Multi Languages Spell Checker for webmaster. Part 5. Multilang asynchronous spell checker with NHunspell. #WinDesktop #Task
- (2019) Multi Languages Spell Checker for webmaster. Part 3. Directory observer on NET Reactive extension. #Task #WinDesktop
- (2019) ASP.NET Core Backend with MailKit/IMAP (Async/Await, Monitor, ConcurrentQueue, CancellationTokenSource) #Task #NetCoreBackend #Mailing
- (2019) 2.1. My typical VB.NET desktop application. (EF DB First and ADO NET Typed Dataset, Tree ways to Binding GridView and ComboBox, Set Timeout, Asynchronous fill table by data) #WinDesktop #Task
- (2018) BackgroundWorkerQueue. #NetCommon #Task
- (2018) How to create Slideshow and VideoConverter by FFmpeg MediaToolkit. #Task #WinDesktop #Video
- (2018) MailKit/MimeKit - best eMail client. #Mailing #NetCommon #Task
- (2018) Multithreading Parsers with Parallel, CsQuery, Newtonsoft.Json, OfficeOpenXml and IAsyncResult/AsyncCallback. #Task
- (2016) TreeView FileSelector by ReactiveNET and TheArtOfDev.HtmlRenderer (SpellChecker project). #Browser #WinDesktop #Yield #Task
- (2016) Mutlithreading InfoMessagBox by ConcurrentQueue, Interlocked and Timer. #Task #Delegate #WinDesktop
- (2016) Building TreeView by Reactive Extensions NET (Recursive observe directory, Iterator function with Yield, Windows native thread). #Task #WinDesktop #Yield
- (2014) My web scrapper with asyncronous web request and visual proxy availability detection. #WinDesktop #Vpn #WebServiceClient #Task
- (2013) Оновлення StatusLabel з потоку BackGroundWorker - приклад застосування Action, Delegate, Invoke, AddressOf, Extension, Expression. #WinDesktop #Delegate #Task
- ...
- (2005) Мультипоточное программирование #Task #NetCommon
- (2005) Работа с классами и коллекциями #WinDesktop #Task
- (2005) My multithreading experience #SectionTask
My multithreading learning conspectus:
- .NET #1
- .NET #2
- Task
- Thread
- Asynchronous Programming Patterns.pdf
- Task-based Asynchronous Pattern.pdf
- Event-based Asynchronous Pattern.pdf
- Asynchronous Programming Model.pdf
- Threading. Programing Concept.pdf
- Threading Objects and Features.pdf
- Managed Thread.pdf
- Asynchronous Programming with Async and Await.pdf
- BackgroundWorker.pdf
- Fine-Tuning Async Application.pdf
- Parallel Programming.pdf

|