<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrew Nosenko</title>
    <description>The latest articles on DEV Community by Andrew Nosenko (@noseratio).</description>
    <link>https://dev.to/noseratio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F233042%2F373f89ad-e043-40ee-a23e-07c25a509c89.jpeg</url>
      <title>DEV Community: Andrew Nosenko</title>
      <link>https://dev.to/noseratio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/noseratio"/>
    <language>en</language>
    <item>
      <title>WPF in 2021: alive, dead or on life support?</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Mon, 26 Jul 2021 09:39:14 +0000</pubDate>
      <link>https://dev.to/noseratio/the-signs-of-wpf-currently-being-on-life-support-1h3a</link>
      <guid>https://dev.to/noseratio/the-signs-of-wpf-currently-being-on-life-support-1h3a</guid>
      <description>&lt;p&gt;Recently I've been participating in a team discussion about whether or not to choose WPF as a framework for a new "greenfield" Windows-only application. The application itself isn't expected to have a sophisticated UI, but it might be required to use WebView2 and/or some 3rd party controls for document rendering, viewing and printing.&lt;/p&gt;

&lt;p&gt;I'm writing this post as someone with substantial .NET/WPF background, who has lots of fond memories about WPF (and some bitter ones, too). I am not trying to diminish the value of this framework, but rather to evaluate where it stands nowadays in Microsoft Desktop development roadmap. &lt;/p&gt;

&lt;p&gt;From what I could tell, these days even Windows Forms is getting more love from Microsoft than WPF. I hope I'm wrong, but I'm observing certain signs of WPF being currently either shelved or placed into a very low-maintenance support mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dotnet/wpf/blob/main/roadmap.md" rel="noopener noreferrer"&gt;The WPF roadmap itself&lt;/a&gt; (or, pretty much, the lack of it, if compared to &lt;a href="https://github.com/dotnet/winforms/blob/main/docs/roadmap.md" rel="noopener noreferrer"&gt;that of WinForms&lt;/a&gt;). According to this document, the only ongoing effort is &lt;em&gt;"incorporating .NET Framework servicing fixes into .NET Core 3.1 and .NET 5"&lt;/em&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://github.com/dotnet/wpf/issues/3904" rel="noopener noreferrer"&gt;"Is this repo dead"&lt;/a&gt; issue in the WPF repo. Lots of interesting comments in that thread, particularly, &lt;a href="https://github.com/dotnet/wpf/issues/3904#issuecomment-744274636" rel="noopener noreferrer"&gt;this one&lt;/a&gt;:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The real reason was already communicated on community calls over on YouTube. The team was merged with WinUI and created from zero, apparently everyone from the original team is gone, and the new team is very resource constrained so they don't manage to deliver more than a couple of fixes. Now we can complain that instead of doing WPF, WinUI, MAUI, Blazor on Electron (what a bad idea!) they should focus on just having one UI-vnext framework, but after UWP failure, they don't seem to be able to decide what to do, each group talks differently about the "vision".&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some folks in that thread even voiced initiatives to fork WPF and maintain it independently of Microsoft.&lt;br&gt;
&lt;br&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Microsoft's Igor Velikorossov on what's new in Windows Forms: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For .NET 5: &lt;a href="https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-runtime-in-net-5-0" rel="noopener noreferrer"&gt;https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-runtime-in-net-5-0&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;For .NET 6 Preview 5: 
&lt;a href="https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0-preview-5" rel="noopener noreferrer"&gt;https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0-preview-5&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;It's great to see WinForms being actively maintained, but what about WPF? Check out the grieving readers' &lt;a href="https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-runtime-in-net-5-0/#comment-8171" rel="noopener noreferrer"&gt;comments&lt;/a&gt;. Back then, Microsoft's PM Premalini David &lt;a href="https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-runtime-in-net-5-0/#comment-8274" rel="noopener noreferrer"&gt;replied&lt;/a&gt; with a promise of boosting up the WPF team internal resources. Looking at &lt;a href="https://github.com/dotnet/wpf/commits/main" rel="noopener noreferrer"&gt;the WPF repo commit history&lt;/a&gt; now, that doesn't seem to have been happening yet.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/desktop/wpf/getting-started/whats-new?view=netframeworkdesktop-4.8&amp;amp;viewFallbackFrom=netdesktop-5.0" rel="noopener noreferrer"&gt;"What's new in WPF for .NET 5"&lt;/a&gt; on docs.microsoft.com. Actually, this page doesn't exist for .NET 5, it falls back to the .NET Framework 4.x content, when you choose ".NET 5". Besides some information on &lt;a href="https://github.com/dotnet/wpf/issues/4117" rel="noopener noreferrer"&gt;adding ARM CPU support&lt;/a&gt;, I couldn't find any details about what's new in WPF since it got ported to .NET Core 3 in 2019. &lt;/p&gt;

&lt;p&gt;&lt;br&gt;On a side note, the "what's new" section &lt;a href="https://docs.microsoft.com/en-us/dotnet/desktop/winforms/whats-new/?view=netdesktop-5.0" rel="noopener noreferrer"&gt;does exist&lt;/a&gt; for .NET 5 Windows Forms.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I expected WPF to be an ultimate container for hosting WebView2, to help modernizing the enterprise desktop WPF apps, which typically still use the legacy IE11-based &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.webbrowser?view=net-5.0" rel="noopener noreferrer"&gt;&lt;code&gt;WebBrowser&lt;/code&gt;&lt;/a&gt; control. As of now, this is far from being the case, either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Rick Strahl's blog post about his titanic efforts on integrating WebView2 into his WPF-based Markdown Monster Editor: &lt;br&gt;&lt;a href="https://weblog.west-wind.com/posts/2021/Apr/15/WebView2-Forwarding-Alt-Keys-to-a-Host-WPF-Window" rel="noopener noreferrer"&gt;https://weblog.west-wind.com/posts/2021/Apr/15/WebView2-Forwarding-Alt-Keys-to-a-Host-WPF-Window&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My own struggle with WPF + WebView2 keyboard and focus issues:&lt;br&gt;&lt;a href="https://github.com/MicrosoftEdge/WebView2Feedback/issues/468#issuecomment-855810839" rel="noopener noreferrer"&gt;https://github.com/MicrosoftEdge/WebView2Feedback/issues/468#issuecomment-855810839&lt;/a&gt;. I believe that can't be properly resolved without making &lt;a href="https://github.com/dotnet/wpf/issues/4637" rel="noopener noreferrer"&gt;changes on the WPF side&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, while there are some ongoing efforts from other teams at Microsoft to continue supporting WPF as a platform (that includes WebView2, BlazorWebView, XAML Islands, Visual Studio Designers), &lt;a href="https://github.com/dotnet/wpf/commits/main" rel="noopener noreferrer"&gt;the WPF GitHub repo itself&lt;/a&gt; has been very quiet lately.&lt;/p&gt;




&lt;p&gt;What's on Microsoft's own radar for Windows-only UI development these days? Well, the official future path appears to be &lt;a href="https://docs.microsoft.com/en-us/windows/apps/winui/" rel="noopener noreferrer"&gt;WinUI 3&lt;/a&gt;. It was in the spotlight during Build 2021 and the recent Windows 11 presentation event. The modern &lt;a href="https://github.com/microsoft/terminal" rel="noopener noreferrer"&gt;Windows Terminal&lt;/a&gt; app — a big open-source hit enjoying a well-deserved recognition — &lt;a href="https://devblogs.microsoft.com/commandline/building-windows-terminal-with-winui" rel="noopener noreferrer"&gt;is built with WinUI&lt;/a&gt; and mostly in C++.&lt;/p&gt;

&lt;p&gt;Microsoft also seems to be big about &lt;a href="https://docs.microsoft.com/en-us/microsoft-edge/webview2/" rel="noopener noreferrer"&gt;WebView2&lt;/a&gt; for the apps where HTML UI is shared between Web and Desktop. The upcoming Teams 2.0 is a good example of such approach, it's a thin WinUI host for WebView2. I ranted with more details about &lt;a href="https://dev.to/noseratio/some-thoughts-on-the-new-microsoft-teams-2-0-architecture-webview2-reactjs-1gf1"&gt;the new Teams 2.0 architecture&lt;/a&gt; (TLTR: it doesn't use .NET on the client side at all). &lt;/p&gt;

&lt;p&gt;Apparently, Microsoft is also well invested into &lt;a href="https://github.com/microsoft/react-native-windows" rel="noopener noreferrer"&gt;React Native for Windows&lt;/a&gt; (a very active repo) and &lt;a href="https://www.microsoft.com/design/fluent/#/windows" rel="noopener noreferrer"&gt;Fluent UI framework&lt;/a&gt; (used by Office 365).&lt;/p&gt;

&lt;p&gt;For .NET folks who want to stick with C# for sharing HTML UI between Web and Desktop (with little or no JavaScript/React/etc), &lt;a href="https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-3/#blazorwebview-controls-for-wpf-windows-forms" rel="noopener noreferrer"&gt;Microsoft will be releasing WebView2-based &lt;code&gt;BlazorWebView&lt;/code&gt;&lt;/a&gt;, supported on WinForms, WPF and .NET MAUI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using Blazor and a hybrid approach you can start decoupling your UI investments from WPF &amp;amp; Windows Forms. This is a great way to modernize existing desktop apps in a way that can be brought forward onto .NET MAUI or used on the web. You can use Blazor to modernize your existing Windows Forms and WPF apps while leveraging your existing .NET investments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sounds like a .NET version of Electron on steroids to me. At this stage, it isn't something I'd like to take for a ride with a new Desktop project, unless there is already a working Blazor SPA web app to wrap as a desktop app. I've tried &lt;code&gt;BlazorWebView&lt;/code&gt; with a simple WinForms-based app, and currently (as of NET 6 Preview 7) &lt;a href="https://github.com/dotnet/maui/issues/2341" rel="noopener noreferrer"&gt;it doesn't feel close&lt;/a&gt; to the production quality yet. Nevertheless, &lt;code&gt;BlazorWebView&lt;/code&gt; is an impressive piece of technology, I hope it will mature and won't be abandoned.&lt;/p&gt;

&lt;p&gt;Besides, the UI technologies Microsoft use for their own mainstream projects aren't necessarily always what they recommend to the rest of the dev world. This can be a particularly confusing domain at the moment, just check this Twitter thread by Jerry Nixon, a Microsoft engineer:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1407013885127933952-300" src="https://platform.twitter.com/embed/Tweet.html?id=1407013885127933952"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1407013885127933952-300');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1407013885127933952&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I'd also highly recommend reading Nick Randolph's &lt;a href="https://www.infoq.com/articles/future-windows-other-platforms-development" rel="noopener noreferrer"&gt;"The Future of Windows (and Other Platforms) Development"&lt;/a&gt;. It's a great take at clarifying the confusion in the fragmented space of various Windows UI frameworks.&lt;/p&gt;




&lt;p&gt;To wrap it up, there is a whole array of frameworks and meta-frameworks to choose from for Windows desktop development nowadays, including some cross-platform options (visit &lt;a href="https://crossplatform.dev/docs/types/" rel="noopener noreferrer"&gt;crossplatform.dev&lt;/a&gt; for a concise overview). A .NET developer can choose from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/dotnet/winforms" rel="noopener noreferrer"&gt;WinForms&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dotnet/wpf" rel="noopener noreferrer"&gt;WPF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/visualstudio/get-started/csharp/tutorial-uwp?view=vs-2019" rel="noopener noreferrer"&gt;UWP&lt;/a&gt; (but be sure to read &lt;a href="https://github.com/microsoft/WindowsAppSDK/discussions/1615#:~:text=what%20if%20i%20have%20a%20uwp%20app%20and%20need%20.net%205%2F6%3F" rel="noopener noreferrer"&gt;this announcement&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/microsoft-ui-xaml" rel="noopener noreferrer"&gt;WinUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dotnet/maui" rel="noopener noreferrer"&gt;Xamarin/MAUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-3/#blazorwebview-controls-for-wpf-windows-forms" rel="noopener noreferrer"&gt;BlazorWebView&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/CommunityToolkit/WindowsCommunityToolkit" rel="noopener noreferrer"&gt;Windows Community Toolkit&lt;/a&gt; (with &lt;a href="https://docs.microsoft.com/en-us/windows/communitytoolkit/mvvm/introduction" rel="noopener noreferrer"&gt;MVVM Toolkit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/unoplatform" rel="noopener noreferrer"&gt;Uno Platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AvaloniaUI/Avalonia" rel="noopener noreferrer"&gt;Avalonia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dotnet/Comet" rel="noopener noreferrer"&gt;Comet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/reactiveui/ReactiveUI" rel="noopener noreferrer"&gt;ReactiveUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/chromelyapps/Chromely" rel="noopener noreferrer"&gt;Chromely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webview2/EdgeSharp" rel="noopener noreferrer"&gt;EdgeSharp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ElectronNET/Electron.NET" rel="noopener noreferrer"&gt;Electron.NET&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... and more. Back to our specific app case, I personally voted for Windows Forms, as odd as it may sound in 2021.&lt;/p&gt;

&lt;p&gt;Some pro-WinForms points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;it is old and battle-tested but still &lt;a href="https://github.com/dotnet/winforms/commits/main" rel="noopener noreferrer"&gt;being actively maintained&lt;/a&gt; (unlike WPF, presently);&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;has a simple, unopinionated and well-know API;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;uses native Win32 UI controls under the hood and therefore …&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;… is easy to integrate with other native and managed controls or modernize with &lt;a href="https://docs.microsoft.com/en-us/microsoft-edge/webview2" rel="noopener noreferrer"&gt;&lt;code&gt;WebView2&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-3/#blazorwebview-controls-for-wpf-windows-forms" rel="noopener noreferrer"&gt;&lt;code&gt;BlazorWebView&lt;/code&gt;&lt;/a&gt; and/or &lt;a href="https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands" rel="noopener noreferrer"&gt;XAML Islands&lt;/a&gt;. I'd expect fewer issues with the focus/keyboard interop as well, or at least, they should be easier to address, than with WPF.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;can be abstracted behind something simple, like &lt;a href="https://markheath.net/post/model-view-presenter-winforms" rel="noopener noreferrer"&gt;Model-View-Presenter Pattern&lt;/a&gt;, or something advanced, like &lt;a href="https://www.reactiveui.net/docs/guidelines/platform/windows-forms" rel="noopener noreferrer"&gt;Reactive UI&lt;/a&gt;;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;can be deployed as a single EXE &lt;del&gt;(~75MB)&lt;/del&gt; without needing admin rights, Windows Store, packaging, sideloading, tweaks to the Windows Developer settings, etc (&lt;em&gt;updated&lt;/em&gt;: &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/incompatibilities" rel="noopener noreferrer"&gt;trimming no longer work in .NET 6 for WinForms/WPF&lt;/a&gt;):&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new winforms -n app

dotnet publish app -r win-x64 -c Release --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=True -p:IncludeNativeLibrariesForSelfExtract=true -p:TrimMode=Link

dir /s app.exe
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've been using the .NET Core reincarnation of WinForms for &lt;a href="https://github.com/postprintum/devcomrade" rel="noopener noreferrer"&gt;#DevComrade&lt;/a&gt;, a small side project. It enables systemwide pasting without formatting by default, amongst a few other productivity improvement features. Building it with WinForms has been a very positive experience so far.&lt;/p&gt;



&lt;h2&gt;
  
  
  Some late updates:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/microsoft/WindowsAppSDK/discussions/1615#:~:text=what%20if%20i%20have%20a%20uwp%20app%20and%20need%20.net%205%2F6%3F" rel="noopener noreferrer"&gt;Microsoft's announcement&lt;/a&gt; about .NET 5/6 support &lt;strong&gt;not&lt;/strong&gt; coming to UWP .NET projects. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:6856737082342297600/" rel="noopener noreferrer"&gt;My take&lt;/a&gt; on the above UWP announcement.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/noseratio/status/1455046924294189056?s=20" rel="noopener noreferrer"&gt;&lt;strong&gt;No&lt;/strong&gt; trimming support&lt;/a&gt; for WinForms and WPF projects in .NET 6.&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://news.ycombinator.com/item?id=28218174" rel="noopener noreferrer"&gt;interesting thread on HN&lt;/a&gt;, discussing current the state of UI development with .NET, amongst other things. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dotnet/wpf/issues/5314" rel="noopener noreferrer"&gt;"The roadmap is outdated"&lt;/a&gt; issue in WPF repo. &lt;/li&gt;
&lt;li&gt;I learnt that WPF is still used in &lt;a href="https://github.com/microsoft/PowerToys" rel="noopener noreferrer"&gt;Microsoft's Powertoy project&lt;/a&gt; and in &lt;a href="https://twitter.com/davidwengier/status/1454915177334251521?s=20" rel="noopener noreferrer"&gt;the new Visual Studio Installer&lt;/a&gt; (migrated from Electron), not to mention VS2022 itself (still a .NET Framework 4.x project though).&lt;/li&gt;
&lt;li&gt;There's hope that WPF team will eventually get a much needed resource boost (although still no signs this is happening, as of Nov'21): &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1454510032985346056-769" src="https://platform.twitter.com/embed/Tweet.html?id=1454510032985346056"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1454510032985346056-769');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1454510032985346056&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Thanks for reading! Feel free to leave a comment below or &lt;a href="https://twitter.com/noseratio" rel="noopener noreferrer"&gt;on Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>desktop</category>
      <category>wpf</category>
      <category>winforms</category>
    </item>
    <item>
      <title>Some thoughts on the new Microsoft Teams 2.0 architecture (WebView2/ReactJS)</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Sat, 17 Jul 2021 12:38:13 +0000</pubDate>
      <link>https://dev.to/noseratio/some-thoughts-on-the-new-microsoft-teams-2-0-architecture-webview2-reactjs-1gf1</link>
      <guid>https://dev.to/noseratio/some-thoughts-on-the-new-microsoft-teams-2-0-architecture-webview2-reactjs-1gf1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Updated on 2021/07/24&lt;/strong&gt;, Electron.js has published a great article on &lt;a href="https://www.electronjs.org/blog/webview2" rel="noopener noreferrer"&gt;comparing Electron to WebView2&lt;/a&gt;. It's reassuring to know an improved form of IPC (between the WV2 host and JavaScript) is coming, in form of &lt;a href="https://cbor.io" rel="noopener noreferrer"&gt;CBOR&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;If you've been following the news from the remote collaboration software industry, you've probably heard that Microsoft Teams have migrated from &lt;strong&gt;Electron/Angular&lt;/strong&gt; to &lt;strong&gt;WebView2/React&lt;/strong&gt; for the upcoming version 2.0, which is also a part of Windows 11. A tweet by Rish Tandon, the CVP of engineering for Teams:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1408085784016539653-81" src="https://platform.twitter.com/embed/Tweet.html?id=1408085784016539653"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1408085784016539653-81');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1408085784016539653&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;As a software engineer who is involved in both web conferencing tools and Windows Desktop app development, I've been curious about this move. Particularly, whether or not they may also be utilizing .NET on the Desktop now, along with WebView2 (and JavaScript interop via &lt;a href="https://docs.microsoft.com/en-us/microsoft-edge/webview2/how-to/javascript" rel="noopener noreferrer"&gt;WebView2 IPC&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;I thought, as long as they don't use Electron anymore and are being more Windows-centric now, they might as well be leveraging the power of .NET to do some media pre-processing on the client side. Similar to what &lt;a href="https://webrtchacks.com/zoom-avoids-using-webrtc" rel="noopener noreferrer"&gt;Zoom is doing with WebAssembly&lt;/a&gt;, but potentially, in a more efficient way with some compiled .NET code?&lt;/p&gt;

&lt;p&gt;I didn't have a chance to install any insider builds of Windows 11 yet, but &lt;a href="https://www.reddit.com/r/MicrosoftTeams/comments/olunv3/now_that_teams_20_uses_webview2_is_there_any/" rel="noopener noreferrer"&gt;with a little help from a fellow redditor&lt;/a&gt;, I managed to get a sneak peek into Teams 2.0 internals, using SysInternals' excellent &lt;a href="https://docs.microsoft.com/en-us/sysinternals/downloads/listdlls" rel="noopener noreferrer"&gt;ListDLLs tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Take these thoughts with a grain of salt, currently they are just mine (somewhat educated) guesses/speculations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Teams 2.0 appears to be a Windows Store package, it's installed under "C:\Program Files\WindowsApps". Presumably, it can be listed from PowerShell with &lt;code&gt;Get-AppxPackage -allusers *teams*&lt;/code&gt;.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;I could not detect any traces of the .NET runtime DLLs&lt;/em&gt; in the memory space of the new Teams process. It does look like they use some Azure C++ SDK DLLs (&lt;code&gt;azure-core.dll&lt;/code&gt;, &lt;code&gt;azure-storage-blobs.dll&lt;/code&gt;, &lt;code&gt;azure-storage-common.dll&lt;/code&gt;), a set of &lt;a href="https://www.boost.org/" rel="noopener noreferrer"&gt;Boost C++ libraries&lt;/a&gt; (&lt;code&gt;boost_*.dll&lt;/code&gt;) and &lt;a href="https://www.sqlite.org/index.html" rel="noopener noreferrer"&gt;SQLite&lt;/a&gt; (&lt;code&gt;sqlite3.dll&lt;/code&gt;, presumably for storing the app's local state).&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They use WebView2 (aka WV2) in &lt;a href="https://docs.microsoft.com/en-gb/microsoft-edge/webview2/concepts/distribution#stay-compatible-in-evergreen-mode" rel="noopener noreferrer"&gt;shared "evergreen" mode&lt;/a&gt; ("C:\Program Files (x86)\Microsoft\EdgeWebView\Application\91.0.864.70\EBWebView\x64\EmbeddedBrowserWebView.dll").&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's now a single-instance &lt;code&gt;msteams.exe&lt;/code&gt; process. This may look as a departure from the multi-process architecture of Electron, but of course, WV2 still runs a bunch of its own &lt;code&gt;msedgewebview2.exe&lt;/code&gt; processes. No surprise here, as it's still a customized version of Chromium under the hood.&lt;br&gt;&lt;br&gt;
Is this pool of WV2 Chromium processes shared across other WV2 instances? I don't think so, but let's &lt;a href="https://github.com/MicrosoftEdge/WebView2Feedback/issues/1542" rel="noopener noreferrer"&gt;ask the WV2 team&lt;/a&gt; directly.&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's hard to tell if they just use pure &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API" rel="noopener noreferrer"&gt;WebRTC API&lt;/a&gt; inside WebView2, or do some custom video processing on the client, but I haven't spotted any FFmpeg-like DLLs or anything that might look like custom codecs (the Electron-based version of Teams does bundle &lt;code&gt;ffmpeg.dll&lt;/code&gt;, although it might just be a part of Electron runtime).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, Teams 2 appears to be a basic &lt;a href="https://docs.microsoft.com/en-us/windows/apps/winui/winui3/create-your-first-winui3-app?tabs=desktop-cpp" rel="noopener noreferrer"&gt;WinUI 3 Desktop C++ App&lt;/a&gt;, &lt;em&gt;not&lt;/em&gt; using WinForms, WPF or any other .NET libraries, with all-HTML UI made with React and hosted in WV2. Except, perhaps, for the UI pieces like top-level menus bar, status bar and Windows native notifications. &lt;/p&gt;

&lt;p&gt;I actually haven't seen the full UI yet, but such approach would make sense if they still aim to share the UI codebase between the Desktop app and the browser web app (at &lt;a href="https://teams.microsoft.com" rel="noopener noreferrer"&gt;https://teams.microsoft.com&lt;/a&gt;). The HTML UI is most likely built with &lt;a href="https://www.microsoft.com/design/fluent/#/web" rel="noopener noreferrer"&gt;Fluent UI React&lt;/a&gt;, in line with the rest of Office 365.&lt;/p&gt;

&lt;p&gt;One issue I've myself dealt with while hosting WV2 in a WPF app was &lt;a href="https://github.com/MicrosoftEdge/WebView2Feedback/issues/468#issuecomment-855810839" rel="noopener noreferrer"&gt;with accelerator keys of native peer WPF controls and menus&lt;/a&gt;, when the focus is inside WV2. It'll be interesting to see if a Win UI 3 host app is also affected by this, how Teams 2.0 deals with this.&lt;/p&gt;

&lt;p&gt;That's the whole picture I've got for now. I'd appreciate if someone who might know more could jump in and correct me. I'll be updating this post as I learn anything new about Teams 2.0 architecture.&lt;/p&gt;

</description>
      <category>windows</category>
      <category>desktop</category>
      <category>webview2</category>
    </item>
    <item>
      <title>Automation with Deno: a tiny text template processor in JavaScript</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Fri, 04 Jun 2021 10:18:20 +0000</pubDate>
      <link>https://dev.to/noseratio/a-nascent-text-template-processor-with-deno-1hd6</link>
      <guid>https://dev.to/noseratio/a-nascent-text-template-processor-with-deno-1hd6</guid>
      <description>&lt;p&gt;Basically, a three-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;templateText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readTextFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;return `&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;templateText&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateParams&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses interpolated JavaScript template strings (aka &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;template literals&lt;/a&gt;) to process a generic text template file. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# example of a YAML template&lt;/span&gt;
&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${ this.dateTime.client_ip }&lt;/span&gt;
  &lt;span class="na"&gt;ip_time_zone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${ this.dateTime.abbreviation }&lt;/span&gt;
  &lt;span class="na"&gt;server_utc_time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${ this.dateTime.utc_datetime }&lt;/span&gt;
  &lt;span class="na"&gt;local_time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${ new Date() }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;em&gt;&lt;code&gt;this&lt;/code&gt;&lt;/em&gt; refers to the &lt;code&gt;templateParams&lt;/code&gt; object we passed from the above Deno script. This text file is in fact just a multi-line template strings, with all the corresponding syntax rules you'd follow inside a JavaScript "backtick" string. Hey, it's even &lt;a href="https://dev.to/noseratio/await-inside-javascript-template-strings-3kbj"&gt;possible to use &lt;code&gt;await&lt;/code&gt;&lt;/a&gt; inside &lt;code&gt;`${...}`&lt;/code&gt; :)  &lt;/p&gt;

&lt;h2&gt;
  
  
  What is this useful for?
&lt;/h2&gt;

&lt;p&gt;I believe it can be useful for build automation, including certain CI/CD-related tasks. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://deno.land/"&gt;Deno&lt;/a&gt; itself is a very self-cointained JavaScript/TypeScript runtime engine. It comes as a single executable file which can be used without any external dependencies. Yet it offers an extensive &lt;a href="https://doc.deno.land/builtin/stable"&gt;built-in API&lt;/a&gt; to deal with files, networking etc. &lt;/p&gt;

&lt;p&gt;More so, any specific Deno version can be easily installed into a local folder without admin rights. E.g., to install Deno v1.10.3 on Windows with PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install Deno v1.10.3 into ./bin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;DENO_INSTALL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pwd&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1.10.3"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;iwr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://deno.land/x/install/install.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-useb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Personally, I've never been comfortably fluent with Bash, PowerShell etc., so I find Deno very handy for quick, shell-like scripting with JavaScript. With Deno, I can quickly run a one-liner like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ deno eval -p "await fetch('https://example.com').then(r =&amp;gt; r.text()).then(t =&amp;gt; t.match('example'))"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, Deno is much more capable than that, but that's outside the scope of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example of templating
&lt;/h2&gt;

&lt;p&gt;This example is a bit contrived, but it illustrates the purpose. Here we make a simple &lt;code&gt;fetch&lt;/code&gt; request to &lt;a href="https://worldtimeapi.org/api/ip"&gt;https://worldtimeapi.org/api/ip&lt;/a&gt; and save the results, using the above YAML template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// deno run --allow-read --allow-net nascentTextGen.js sample.yaml.template &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;templateParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dateTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://worldtimeapi.org/api/ip&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;templateText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readTextFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;return `&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;templateText&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateParams&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# example of a YAML template&lt;/span&gt;
&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;a.b.c.d&lt;/span&gt;
  &lt;span class="na"&gt;ip_time_zone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AEST&lt;/span&gt;
  &lt;span class="na"&gt;server_utc_time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2021-06-04T01:32:56.595373+00:00&lt;/span&gt;
  &lt;span class="na"&gt;local_time&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Fri Jun 04 2021 11:32:55 GMT+1000 (Australian Eastern Standard Time)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Clone or fork &lt;a href="https://github.com/noseratio/nascentTextGen"&gt;this simpe demo project&lt;/a&gt;. Then: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to install Deno (PowerShell):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pwsh -f _installDeno.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;to run the sample:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pwsh -f _demo.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Some more advanced general-purpose templating tools
&lt;/h2&gt;

&lt;p&gt;This little project was inspired by &lt;a href="https://twitter.com/noseratio/status/1399682377446690819?s=20"&gt;a search for a JavaScript-based general-purpose text templating tool&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Of course, this approach may only be useful for simple, "logic-less" templates. If you need branching and looping constructs like &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; or &lt;code&gt;function&lt;/code&gt;, there are a lot more powerful and actively maintained alternatives out there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nunjucks: &lt;a href="https://github.com/mozilla/nunjucks"&gt;https://github.com/mozilla/nunjucks&lt;/a&gt;
(there's even &lt;a href="https://github.com/ronnidc/vscode-nunjucks"&gt;a VSCode extension&lt;/a&gt; for Nunjucks)&lt;/li&gt;
&lt;li&gt;Mustache: &lt;a href="https://github.com/janl/mustache.js"&gt;https://github.com/janl/mustache.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;EJS: &lt;a href="https://github.com/mde/ejs"&gt;https://github.com/mde/ejs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;T4 (C#/.NET): &lt;a href="https://github.com/mono/t4"&gt;https://github.com/mono/t4&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;and &lt;a href="https://medium.com/@wavded/template-systems-in-node-7f2787d12dbf"&gt;more...&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>deno</category>
    </item>
    <item>
      <title>Await inside JavaScript template strings</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Wed, 02 Jun 2021 06:59:27 +0000</pubDate>
      <link>https://dev.to/noseratio/await-inside-javascript-template-strings-3kbj</link>
      <guid>https://dev.to/noseratio/await-inside-javascript-template-strings-3kbj</guid>
      <description>&lt;p&gt;Did you know it is possible to use &lt;code&gt;await&lt;/code&gt; inside interpolated JavaScript template strings (aka &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;template literals&lt;/a&gt;)? I personally did not, and have just discovered that by an accident.&lt;/p&gt;

&lt;p&gt;For example, try this with Node or Deno (&lt;a href="https://runkit.com/noseratio/asyncinterpolated-mjs"&gt;runkit&lt;/a&gt; and &lt;a href="https://gist.github.com/noseratio/621b208ea72a8056654ce08b84fccac8"&gt;gist&lt;/a&gt;; save the code as &lt;code&gt;.mjs&lt;/code&gt; so it runs as an ESM module):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interpolated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interpolated&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code works in the browser console as well, verified for Chrome/Edge/Firefox.&lt;/p&gt;

&lt;p&gt;It does require the top-level await support, or otherwise has to reside inside an &lt;code&gt;async&lt;/code&gt; function, as it's basically just a syntactic sugar for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interpolated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why would this feature be useful? For one thing, I can think of a &lt;em&gt;poor man's&lt;/em&gt; text templating engine for JavaScript, where instead of &lt;code&gt;delay&lt;/code&gt; we might be using something like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://nodejs.org/api/fs.html#fs_filehandle_readfile_options"&gt;&lt;code&gt;readFile&lt;/code&gt;&lt;/a&gt; or any other &lt;code&gt;Promise&lt;/code&gt;-based APIs.&lt;/p&gt;

&lt;p&gt;For now, I've added this to my collection of &lt;a href="https://dev.to/noseratio/a-few-handy-javascript-tricks-an9"&gt;a few handy JavaScript tricks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Updated&lt;/strong&gt;, here's a follow-up article: &lt;a href="https://dev.to/noseratio/a-nascent-text-template-processor-with-deno-1hd6"&gt;Automation with Deno: a tiny text template processor in JavaScript&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>async</category>
      <category>await</category>
    </item>
    <item>
      <title>Syntactic sugar: yet another async/await question for JavaScript interviews</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Tue, 04 May 2021 11:08:55 +0000</pubDate>
      <link>https://dev.to/noseratio/yet-another-async-await-question-for-javascript-interviews-1hon</link>
      <guid>https://dev.to/noseratio/yet-another-async-await-question-for-javascript-interviews-1hon</guid>
      <description>&lt;p&gt;Whenever I stumble upon &lt;em&gt;"[something] is a syntactic sugar"&lt;/em&gt;, I appreciate when it is accompanied by a good technical explanation of &lt;em&gt;what&lt;/em&gt; exactly that particular "sugar" is translated to behind the scene. Which isn't always the case.&lt;/p&gt;

&lt;p&gt;For instance, try googling &lt;a href="https://www.google.com/search?q=async+await+syntactic+sugar"&gt;"async await syntactic sugar"&lt;/a&gt;. I don't think the statements like &lt;em&gt;"async is a syntactic sugar for promises"&lt;/em&gt; are very helpful in grokking &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;. In my opinion, the concept of the &lt;a href="https://en.wikipedia.org/wiki/Finite-state_machine"&gt;&lt;em&gt;finite-state machine&lt;/em&gt;&lt;/a&gt; would be very important in this context, yet I couldn't spot the phrase &lt;em&gt;"state machine"&lt;/em&gt; in the top Google-quoted results. &lt;/p&gt;

&lt;p&gt;So, here is one question I personally find interesting and relevant for the both sides of a JavaScript/TypeScript interview (as well as C#, F#, Python, Dart or any other programming language which has adopted the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;How would you go about implementing the following &lt;code&gt;async&lt;/code&gt; function &lt;code&gt;&amp;lt;funcName&amp;gt;&lt;/code&gt; as a simple state machine, without using the keywords &lt;code&gt;async&lt;/code&gt;, &lt;code&gt;await&lt;/code&gt; or &lt;code&gt;yield&lt;/code&gt;?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think it's a one-shot-many-kills kind of question, potentially covering the knowledge of the basic topics like &lt;em&gt;promises&lt;/em&gt;, &lt;em&gt;closures&lt;/em&gt;, &lt;em&gt;exception handling&lt;/em&gt;, &lt;em&gt;recursion&lt;/em&gt;, in addition to &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; and the state machine concepts themselves.&lt;/p&gt;

&lt;p&gt;For a practical JavaScript example, let's take the following simple asynchronous workflow function, &lt;code&gt;loopWithDelay&lt;/code&gt;. It runs a loop doing something useful (&lt;code&gt;doWhat&lt;/code&gt;), with a certain minimal interval between iterations, until the &lt;code&gt;stopWhen&lt;/code&gt; callback signals the end of the loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;loopWithDelay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;doWhat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;minInterval&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;minInterval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;doWhat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`resumed after &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;finished.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We might be calling &lt;code&gt;loopWithDelay&lt;/code&gt; like below (&lt;a href="https://runkit.com/noseratio/loopwithdelay"&gt;runkit&lt;/a&gt;). In JavaScript, anything can be awaited, so this works regardless of whether or not &lt;code&gt;doWhat&lt;/code&gt; returns a promise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;loopWithDelay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;doWhat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doSomethingForMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="na"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stopAfterMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="na"&gt;minInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// a higher-order helper to simulate an asynchronous task&lt;/span&gt;
&lt;span class="c1"&gt;// (for doWhat)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;doSomethingForMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startTimeLapse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// simulate an asynchronous task &lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`done something for the &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
      &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; time, it took &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// a higher-order helper to tell when to stop&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;stopAfterMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startTimeLapse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// a simple delay helper (in every single codebase :)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// a higher-order helper to calculate a timelapse&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;startTimeLapse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="c1"&gt;// a higher-order helper for a minimal interval delay&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;startInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sinceStarted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startTimeLapse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sinceDelayed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startTimeLapse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;sinceStarted&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sinceDelayed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, there are many ways to rewrite this &lt;code&gt;loopWithDelay&lt;/code&gt; without using &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;. We don't have to stricly follow a typical state machine implementation as done by programming language compilers (which can be a bit intimidating, e.g., &lt;a href="https://www.typescriptlang.org/play?target=1&amp;amp;jsx=0&amp;amp;module=0#code/IYZwngdgxgBAZgV2gFwJYHsIwDbvQBwHVVkALAEQFNtgwAKAbxgBN1DThkAaGEZA9pQg8AtqggBJCMkoAnAG7BsMAL4BKGAwBQMGAHdSqbJRh0AhHwGkhdNRu27dUTHxjiZCpTAC8vZMFlkKQ9FbDoxSWk5ULUAbh1HYD1gEhY2DmRbeMcYZwhXERAfGCSU5DcozzC4hKcXdGMAOlwAczoAA1lKEAQRSmYSuA8YABIGQpVCxun2mt0VBLyQBspm9DaAIjhxVBBrZkaNmpUgA"&gt;look at what&lt;/a&gt; TypeScript generates when it targets ES5. Interestingly, when targeting ES2015, TypeScript transpiles &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; &lt;a href="https://www.typescriptlang.org/play?target=2&amp;amp;jsx=0&amp;amp;module=0#code/IYZwngdgxgBAZgV2gFwJYHsIwDbvQBwHVVkALAEQFNtgwAKAbxgBN1DThkAaGEZA9pQg8AtqggBJCMkoAnAG7BsMAL4BKGAwBQMGAHdSqbJRh0AhHwGkhdNRu27dUTHxjiZCpTAC8vZMFlkKQ9FbDoxSWk5ULUAbh1HYD1gEhY2DmRbeMcYZwhXERAfGCSU5DcozzC4hKcXdGMAOlwAczoAA1lKEAQRSmYSuA8YABIGQpVCxun2mt0VBLyQBspm9DaAIjhxVBBrZkaNmpUgA"&gt;using generators&lt;/a&gt; as an optimization). &lt;/p&gt;

&lt;p&gt;To implement &lt;code&gt;loopWithDelay&lt;/code&gt; manually as a state machine, we need to break down the normal flow control statements (in our case, the &lt;code&gt;while&lt;/code&gt; loop) into individual states. These states will be transitioning to one another at the points of &lt;code&gt;await&lt;/code&gt;. Here's one take at that, &lt;code&gt;loopWithDelayNonAsync&lt;/code&gt; (&lt;a href="https://runkit.com/noseratio/loopwithdelaynonasync"&gt;runkit&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;loopWithDelayNonAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;doWhat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;minInterval&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolveWorkflow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rejectWorkflow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// a helper to transition to the next state, &lt;/span&gt;
    &lt;span class="c1"&gt;// when a pending promise from &lt;/span&gt;
    &lt;span class="c1"&gt;// the previous state is fulfilled&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// we fail the whole workflow when &lt;/span&gt;
      &lt;span class="c1"&gt;// the pending promise is rejected or&lt;/span&gt;
      &lt;span class="c1"&gt;// when next() throws &lt;/span&gt;
      &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rejectWorkflow&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// start with step1&lt;/span&gt;
    &lt;span class="nx"&gt;step1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// step1 will transition to step2 after completing a doWhat task&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;step1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// start the interval timing here&lt;/span&gt;
        &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;minInterval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// doWhat may or may not return a promise, &lt;/span&gt;
        &lt;span class="c1"&gt;// thus we wrap its result with a promise&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doWhat&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nx"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;step2&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; 
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// finish the whole workflow &lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;finished.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;resolveWorkflow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// step2 will transition to step3 after completing a delay&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;step2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;step3&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// step3 will transition to step1 after showing the time lapse&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;step3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevStepResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// prevStepResults is what the pending promise &lt;/span&gt;
      &lt;span class="c1"&gt;// from step2 has been resolved to&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`resumed after &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prevStepResults&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;step1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;loopWithDelayNonAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;doWhat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doSomethingForMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="na"&gt;stopWhen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stopAfterMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
  &lt;span class="na"&gt;minInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Equipped with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;, we should never have to write code like &lt;code&gt;loopWithDelayNonAsync&lt;/code&gt; in real life. It still might be a useful exercise though, especially for folks who first got into JavaScript &lt;a href="https://v8.dev/blog/v8-release-55"&gt;after it had received&lt;/a&gt; the native support for &lt;code&gt;async&lt;/code&gt; functions. &lt;/p&gt;

&lt;p&gt;Rather than taking &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntactic sugar for granted, I think it helps to understand how it works behind the scene as a state machine. It also amplifies how versatile, concise and readable the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax is.&lt;/p&gt;

&lt;p&gt;For a deep dive into &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; under the hood in JavaScript, the V8 blog has an awesome article: &lt;a href="https://v8.dev/blog/fast-async"&gt;"Faster async functions and promises"&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>async</category>
      <category>await</category>
      <category>promise</category>
    </item>
    <item>
      <title>A few handy JavaScript tricks</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Tue, 01 Dec 2020 11:45:01 +0000</pubDate>
      <link>https://dev.to/noseratio/a-few-handy-javascript-tricks-an9</link>
      <guid>https://dev.to/noseratio/a-few-handy-javascript-tricks-an9</guid>
      <description>&lt;p&gt;I'd like to document a few neat JavaScript tricks and patterns I've recently learnt from Twitter and other online resources (which I sadly haven't kept track of). All the credits go to the online JavaScript community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;class&lt;/code&gt; is an expression, what it extends is also an expression&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;this&lt;/code&gt; in static class methods&lt;/li&gt;
&lt;li&gt;Invoking an IIFE without extra brackets&lt;/li&gt;
&lt;li&gt;Invoking an async IIFE without extra brackets&lt;/li&gt;
&lt;li&gt;Destructuring of a function argument inline&lt;/li&gt;
&lt;li&gt;Partial destructuring of a function argument inline&lt;/li&gt;
&lt;li&gt;Using expressions in &lt;code&gt;switch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Passing a non-function object as event handler to &lt;code&gt;addEventListener&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Checking if a variable is of specific type&lt;/li&gt;
&lt;li&gt;Checking if a variable is &lt;code&gt;nullish&lt;/code&gt; (i.e., &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Converting to primitive types with &lt;code&gt;Symbol.toPrimitive&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A mnemonic way of ignoring promise errors (where applicable)&lt;/li&gt;
&lt;li&gt;Thenables can be useful side-by-side with promises&lt;/li&gt;
&lt;li&gt;Telling which promise has settled first in &lt;code&gt;Promise.race&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;"Promisifying" a synchronous function call to defer exception handling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Symbol.species&lt;/code&gt; can be useful when extending standard classes&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/noseratio/await-inside-javascript-template-strings-3kbj"&gt;&lt;code&gt;await&lt;/code&gt; can be used inside string templates&lt;/a&gt;
&lt;a&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;class&lt;/code&gt; is an expression, what it extends is also an expression
&lt;/h4&gt;

&lt;p&gt;Similar to &lt;code&gt;function funcName() { ... }&lt;/code&gt;, &lt;code&gt;class className { ... }&lt;/code&gt; is an expression which can be assigned to a variable or passed over as a function argument. And &lt;code&gt;className&lt;/code&gt; here can be optional as well, like with anonymous functions. More so, the base class is also an expression. For example, the following is possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Base1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;whatAmI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Base1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Base2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;whatAmI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Base2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createDerivedClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;whatAmI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Derived from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;whatAmI&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Derived1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createDerivedClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Base1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// output: Derived from Base1&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Derived1&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;whatAmI&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Derived2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createDerivedClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Base2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// output: Derived from Base2&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Derived2&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;whatAmI&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be useful for dynamic compositions of class inheritance trees, including &lt;em&gt;mixins&lt;/em&gt;. I've learnt about it from Justin Fagnani's excellent &lt;a href="https://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes"&gt;"Mixins and Javascript: The Good, the Bad, and the Ugly."&lt;/a&gt;&lt;br&gt;
&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Conveniently, &lt;code&gt;this&lt;/code&gt; in static class methods refers to the class itself
&lt;/h4&gt;

&lt;p&gt;Thus, polymorphism is possible for static methods, like with &lt;code&gt;oncreate&lt;/code&gt; method below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Base&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oncreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;oncreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Something of the base class &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
      &lt;span class="nx"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has been created.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Derived&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Derived&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;oncreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`It's a new instance of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
      &lt;span class="nx"&gt;Derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, all right!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// output: Something of the base class Base has been created.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 

&lt;span class="c1"&gt;// output: It's a new instance of Derived, all right!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
&lt;span class="c1"&gt;// output: true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;derived&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Derived&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I learnt about &lt;code&gt;new this()&lt;/code&gt; when I stumbled upon &lt;a href="https://twitter.com/RReverser/status/695678489937186816"&gt;this tweet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Invoking an IIFE (Immediately Invoked Function Expression) without extra brackets
&lt;/h4&gt;

&lt;p&gt;We can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void"&gt;&lt;code&gt;void&lt;/code&gt; operator&lt;/a&gt; for that, where &lt;code&gt;void&lt;/code&gt; clearly indicates we want to discard the result of an &lt;em&gt;expression&lt;/em&gt; (which an IIFE itself is):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stop?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;debugger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}();&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I believe it's more readable and mnemonic than wrapping the function with brackets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stop?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;debugger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we do need the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rgb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FF0000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#00FF00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0000FF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Invoking an &lt;code&gt;async&lt;/code&gt; IIFE (Immediately Invoked Function Expression)
&lt;/h4&gt;

&lt;p&gt;Similarly to the above, we don't need the wrapping brackets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`elapsed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Destructuring of a function argument inline
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Partial destructuring of a function argument inline
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Using expressions in &lt;code&gt;switch&lt;/code&gt;
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// the first `case` which expression is `true` wins&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;freezing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cold&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cool&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Passing a non-function object as event handler to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener"&gt;&lt;code&gt;addEventListener&lt;/code&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;The trick is to implement &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventListener"&gt;&lt;code&gt;EventListener.handleEvent&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;handleEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; : &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Checking if a variable is of specific type
&lt;/h4&gt;

&lt;p&gt;This method works for both primitive value types and their wrapper classes: &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Number&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt;, &lt;code&gt;Object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Could you predict which console output is common for &lt;code&gt;s1&lt;/code&gt; and &lt;code&gt;s2&lt;/code&gt; snippets below?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I could not, so I've made a &lt;a href="https://runkit.com/noseratio/object-constructor"&gt;RunKit&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s1 instanceof String: false
typeof s1: string
s1.constructor === String: true
s2 instanceof String: true
typeof s2: object
s2.constructor === String: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, it's only &lt;code&gt;s1.constructor === String&lt;/code&gt; and &lt;code&gt;s2.constructor === String&lt;/code&gt; which are consistently &lt;code&gt;true&lt;/code&gt; for both &lt;code&gt;s1&lt;/code&gt; (a primitive string value) and &lt;code&gt;s2&lt;/code&gt; (an instance of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#String_primitives_and_String_objects"&gt;&lt;code&gt;String&lt;/code&gt; class&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/noseratio/the-divine-coercion-between-typescript-basic-types-their-wrappers-simple-objects-and-classes-9p7"&gt;It's even more fun in TypeScript&lt;/a&gt;, which may feel odd for a person coming to JavaScript with C# or Java background.&lt;/p&gt;

&lt;p&gt;So, to check if variable &lt;code&gt;s&lt;/code&gt; represents a string, the following works equally well for primitive values and their wrapping class types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also make it work across realms (an &lt;code&gt;iframe&lt;/code&gt; or a popup):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some may argue that we shouldn't be using class wrappers for primitive values at all. Indeed, we should not. But we have an option to make &lt;em&gt;our own code&lt;/em&gt; behave correctly when it is called by a 3rd party, no matter if it's given a primitive value or a wrapper class object as an argument.&lt;/p&gt;

&lt;p&gt;For example, the following works consistently for all three cases (note the use of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf"&gt;&lt;code&gt;valueOf&lt;/code&gt;&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;takeBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;takeBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;takeBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;takeBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is false&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking if a variable is &lt;code&gt;nullish&lt;/code&gt; (i.e., &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Traditionally, this is done with &lt;em&gt;loose equality&lt;/em&gt; operator &lt;code&gt;==&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is either null or undefined&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// both true &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might arguably be &lt;a href="https://dorey.github.io/JavaScript-Equality-Table/unified/"&gt;the only meaningful use&lt;/a&gt; of the loose equality &lt;code&gt;==&lt;/code&gt; operator (as opposed to the &lt;em&gt;strict equality&lt;/em&gt; operator &lt;code&gt;===&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;If however you want to avoid using &lt;code&gt;==&lt;/code&gt; and &lt;code&gt;!=&lt;/code&gt; operators by all means, below are some alternative ways of performing the "nullish" check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The nullish coalescing (??) operator returns &lt;/span&gt;
&lt;span class="c1"&gt;// its right-hand side operand when its left-hand side operand &lt;/span&gt;
&lt;span class="c1"&gt;// is null or undefined, and otherwise returns &lt;/span&gt;
&lt;span class="c1"&gt;// its left-hand side operand.&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is either null or undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is either null or undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is either null or undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// all standard or properly derived custom JavaScript objects &lt;/span&gt;
&lt;span class="c1"&gt;// have standard properties like these:&lt;/span&gt;
&lt;span class="c1"&gt;// `constructor`, `valueOf`, `toString`.&lt;/span&gt;
&lt;span class="c1"&gt;// Note though the below doesn't work for exotic cases, &lt;/span&gt;
&lt;span class="c1"&gt;// e.g. where a = Object.create(null):&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is neither null nor undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is either null or undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// a is either null or undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's nice about the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators"&gt;optional chaining operator&lt;/a&gt; is that the result is unambiguously &lt;code&gt;undefined&lt;/code&gt; when &lt;code&gt;a&lt;/code&gt; is either &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. This allows for some fancy expressions like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Derived&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numericArg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// make sure the argument we pass to the base class'&lt;/span&gt;
    &lt;span class="c1"&gt;// constructor is either a Number or DEFAULT_VALUE&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numericArg&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_VALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;numericArg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One notable thing about the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator"&gt;nullish coalescing operator&lt;/a&gt; is that in &lt;code&gt;a ?? DEFAULT_VALUE&lt;/code&gt; it will pick &lt;code&gt;DEFAULT_VALUE&lt;/code&gt; when &lt;code&gt;a&lt;/code&gt; is either &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; (as opposed to &lt;code&gt;a || DEFAULT_VALUE&lt;/code&gt;, which picks &lt;code&gt;DEFAULT_VALUE&lt;/code&gt; when &lt;code&gt;a&lt;/code&gt; is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy"&gt;&lt;code&gt;falsy&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Converting to primitive types with &lt;code&gt;Symbol.toPrimitive&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The well-know symbol &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive"&gt;&lt;code&gt;Symbol.toPrimitive&lt;/code&gt;&lt;/a&gt; defines how an object can be converted to primitive types, as in the example below. Note also the use of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag"&gt;&lt;code&gt;Symbol.toStringTag&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toPrimitive&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// hint can be "number", "string", and "default" &lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Item: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toStringTag&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* Output:
42
Item: 42
[object Item]
Item {}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A mnemonic way of ignoring promise errors (where applicable)
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This literally says: &lt;em&gt;"void that error"&lt;/em&gt; and it is ESLint-friedly. I see it becoming increasingly useful, to avoid potential troubles with &lt;a href="https://stackoverflow.com/a/64344718"&gt;unhandled promise rejections&lt;/a&gt; in Node v15+. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// • we may want to start workflow1 before workflow2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workflow1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workflow2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// • and we may need workflow2 results first&lt;/span&gt;
&lt;span class="c1"&gt;// • if it fails, we don't care about the results of workflow1&lt;/span&gt;
&lt;span class="c1"&gt;// • therefore, we want to prevent &lt;/span&gt;
&lt;span class="c1"&gt;//   unwanted unhandled rejection for promise1&lt;/span&gt;
&lt;span class="nx"&gt;promise1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// • observe workflow2 results first&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="c1"&gt;// • if the above didn't throw, now observe workflow1 results&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Thenables can be useful side-by-side with promises
&lt;/h4&gt;

&lt;p&gt;I've previously blogged &lt;a href="https://dev.to/noseratio/we-can-make-any-javascript-object-await-able-with-then-method-1apl"&gt;about thenables&lt;/a&gt;. In a nutshell, here's how to create a &lt;a href="https://api.jquery.com/jquery.deferred/"&gt;&lt;code&gt;jQuery.Deferred&lt;/code&gt;&lt;/a&gt;-like thenable object that can be awaited:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createDeferred&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createDeferred&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// resolve the deferred in 2s &lt;/span&gt;
&lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Telling which promise has settled first in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race"&gt;&lt;code&gt;Promise.race&lt;/code&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Sometimes we need to know which promise became resolved or rejected first and thus won the race with &lt;code&gt;Promise.race&lt;/code&gt;, similarly to &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenany?view=net-5.0"&gt;&lt;code&gt;Task.WhenAny&lt;/code&gt;&lt;/a&gt; in .NET. Linking my &lt;a href="https://stackoverflow.com/a/64723870/1768303"&gt;SO answer&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * When any promise is resolved or rejected, 
 * returns that promise as the result.
 * @param  {Iterable.&amp;lt;Promise&amp;gt;} iterablePromises An iterable of promises.
 * @return {{winner: Promise}} The winner promise.
 */&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;whenAny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iterablePromises&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;getRacers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;iterablePromises&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}());&lt;/span&gt;

  &lt;span class="c1"&gt;// return the winner promise as an object property, &lt;/span&gt;
  &lt;span class="c1"&gt;// to prevent automatic promise "unwrapping"&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;winner&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  "Promisifying" a synchronous function call to defer exception handling
&lt;/h4&gt;

&lt;p&gt;Credits: &lt;a href="https://github.com/tc39/proposal-promise-try"&gt;tc39-proposal-promise-try&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ensureEven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Uneven!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// • this throws:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ensureEven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// • this doesn't throw:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ensureEven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// • until it is awaited&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// • alternatively:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ensureEven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hopefully, soon we'll be able to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ensureEven&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Until then, we can also use a polyfill like &lt;a href="https://twitter.com/RReverser/status/695678489937186816"&gt;this one&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Symbol.species&lt;/code&gt; can be useful when extending standard classes
&lt;/h4&gt;

&lt;p&gt;The well-know symbol &lt;code&gt;Symbol.species&lt;/code&gt; was definitely little-known to me. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/species"&gt;MDN describes it&lt;/a&gt; as symbol that &lt;em&gt;specifies a function-valued property that the constructor function uses to create derived objects&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What it means in reality is that sometimes JavaScript needs to create a fresh instance of an object, i.e., to reproduce an object without cloning. For example, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"&gt;&lt;code&gt;Array.prototype.map&lt;/code&gt;&lt;/a&gt; creates a new array instance before doing any mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UltraArray&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UltraArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;UltraArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might be tempting to think about such kind of object reproduction this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In reality though, it's done a bit differently, more like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;species&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, if we want &lt;code&gt;map&lt;/code&gt; to use the base class &lt;code&gt;Array&lt;/code&gt; for a new mapped instance, when &lt;code&gt;map&lt;/code&gt; is invoked on an object of our custom class &lt;code&gt;UltraArray&lt;/code&gt;, we can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UltraArray&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;species&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UltraArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;UltraArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Array&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When could this feature (seemingly not so useful) still be important? My answer would be: &lt;em&gt;for deriving from and extending the standard &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;&lt;code&gt;Promise&lt;/code&gt;&lt;/a&gt; class with added functionality like &lt;code&gt;DeferredPromise&lt;/code&gt;, &lt;code&gt;AbortablePromise&lt;/code&gt;, etc.&lt;/em&gt; This probably deserves a separate blog post, which I plan to publish soon.&lt;/p&gt;

&lt;h4&gt;
  
  
  I hope you find these tips helpful
&lt;/h4&gt;

&lt;p&gt;I plan to keep this post updated as I discover more fun JavaScript bits and pieces. Consider &lt;a href="https://twitter.com/noseratio"&gt;following me on Twitter&lt;/a&gt; if interested in these updates.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>promises</category>
    </item>
    <item>
      <title>Grokking type conversion between TypeScript basic types, classes instances and object literals</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Wed, 25 Nov 2020 01:22:24 +0000</pubDate>
      <link>https://dev.to/noseratio/the-divine-coercion-between-typescript-basic-types-their-wrappers-simple-objects-and-classes-9p7</link>
      <guid>https://dev.to/noseratio/the-divine-coercion-between-typescript-basic-types-their-wrappers-simple-objects-and-classes-9p7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Edited&lt;/strong&gt;: I've now filed a related issue in the TypeScript repo: &lt;br&gt;
&lt;a href="https://github.com/microsoft/TypeScript/issues/42698"&gt;&lt;em&gt;A flag to make TypeScript more strict towards duck-typing classes&lt;/em&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
A disclaimer: this post is coming from an OOP/C# person with a solid JavaScript background who's slowly learning TypeScript. If you're a TypeScript ninja, you should probably be already aware of these language specifics. I admit I should have thoroughly read the &lt;a href="https://www.typescriptlang.org/docs/handbook/"&gt;Handbook&lt;/a&gt; before starting coding with TypeScript, but who has time for that? :)

&lt;p&gt;&lt;br&gt;Let me start with a simple question, could you predict the output from the following TypeScript snippet?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a &lt;a href="https://www.typescriptlang.org/play?#code/DYUwLgBAzgjAXBAymATgSwHYHMIF4IBEUBA3BAFADGA9hlNaAHTDVYAUsEmUYAhhpRDUAZklSYsASiq16TFuzABPAA5DRsaTToMQzVhxiNtPFAFdKYaijy58ydNmlA"&gt;playground link&lt;/a&gt; for your convenience, and the output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;false 
"string" 
true 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, &lt;code&gt;s1&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; an instance of &lt;code&gt;String&lt;/code&gt; (despite typed so), its &lt;code&gt;typeof&lt;/code&gt; type is &lt;code&gt;"string"&lt;/code&gt; but its &lt;code&gt;constructor&lt;/code&gt; is nevertheless &lt;code&gt;String&lt;/code&gt;. Coming from C#, this doesn't make a lot of sense 🙂 &lt;/p&gt;

&lt;p&gt;Now, try predicting this output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a &lt;a href="https://www.typescriptlang.org/play?#code/DYUwLgBAzgTAXBAymATgSwHYHMIF4IYgDuSqmWAFAERRUCUA3BAFADGA9hlO6AHTDtKsCJihgAhhlYh2AM1LpsdNp258BlMAE8ADjPmxlHLjxD9BFWL2NiUAV1Zh2KPLnzJFWZUA"&gt;playground link&lt;/a&gt;, and the output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;true 
"object" 
true 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;s2&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; an instance of &lt;code&gt;String&lt;/code&gt;, its &lt;code&gt;typeof&lt;/code&gt; type is now &lt;code&gt;"object"&lt;/code&gt; but its &lt;code&gt;constructor&lt;/code&gt; is still &lt;code&gt;String&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Finally, this one (&lt;a href="https://www.typescriptlang.org/play?#code/DYUwLgBAzgzAXNMAnAlgOwOYQLwQERR4DcEAUAMYD2aUloAdMJRgBSwTpRgCGa5IlAGYQAysnQYAlBAD0MiCCRJKSCtVoMmrMAE8ADgOGxJamnRCNmbGPSo1kAV3JgVObLjGpMJoA"&gt;playground&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// TypeScript error&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;false 
"string" 
true 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might be confusing, but it makes sense if we recall that TypeScript doesn't have any runtime type system (unlike C#). It just emits JavaScript, using whatever nascent type system the current ECMAScript version of JavaScript has. &lt;/p&gt;

&lt;p&gt;For example, the generated JavaScript for the first code snippet looks like this (compiled with &lt;code&gt;tsc -t ESNext code.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a C# person, I might expect TypeScript to turn &lt;code&gt;let s1: String = "s"&lt;/code&gt; into &lt;code&gt;let s1 = new String("s")&lt;/code&gt; in JavaScript, because I declared &lt;code&gt;s1&lt;/code&gt; to be of a non-basic, class type &lt;code&gt;String&lt;/code&gt; (rather than of a basic, primitive value type &lt;code&gt;string&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Well, this is not how it works. Why? I asked &lt;a href="https://stackoverflow.com/q/64941184/1768303"&gt;this question&lt;/a&gt; on StackOverflow, and I got an &lt;a href="https://stackoverflow.com/a/64948481/1768303"&gt;excellent answer&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is specifically &lt;a href="https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals#non-goals"&gt;a non-goal of the TypeScript language design&lt;/a&gt; to "add or rely on run-time type information in programs, or emit different code based on the results of the type system". So any suggestion or expectation of this sort should not be made.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To dig a bit deeper, the same relationship is true for classes and simple anonymous objects in TypeScript (&lt;a href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIGFkG8BQz-IDOAXEWFKAOYDcOAvjjggDZyGHKbAC2ADsxG4RwHDNjwESZCiBoT8CAPYhC5AK4IwiqAAopqmZQCU4gmeRgAFsEIA6DgF4itMwwZNlq5AgCMpTE4gEADunDoARL7hRrRKKooCtsyKlDq+yKCqcCBIijCcMcgA9EUWUGoQjHFeCABM-shOWESkkbXhyHSxngkQSSlptRkqYNm5+eiFJcjwzISVHiPeAMykYk0tyJHLHV2LhL39qWnLyGwFw1k5EHkX07PzjEA"&gt;playground&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IC&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IC&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c1&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c2&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c3&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works the way it does because &lt;a href="https://www.typescriptlang.org/docs/handbook/interfaces.html"&gt;TypeScript is a "duck typing" language&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Note the &lt;code&gt;as&lt;/code&gt; operator? This is a &lt;a href="https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions"&gt;"type &lt;em&gt;assertion&lt;/em&gt;"&lt;/a&gt;, rather than some kind of type conversion that might affect the generated code. It will &lt;em&gt;not&lt;/em&gt; magically turn an anonymous object into a instance of a class.&lt;/p&gt;

&lt;p&gt;If the object is of type &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;unknown&lt;/code&gt;, the &lt;code&gt;as&lt;/code&gt; operator simply tells TypeScript that (to our best knowledge) the object has the expected set of properties and methods of the target type, to avoid &lt;em&gt;compile-time&lt;/em&gt; errors. If that's not true, we'll most likely experience runtime errors.&lt;/p&gt;

&lt;p&gt;If the object is anything other type than &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;unknown&lt;/code&gt;, the &lt;code&gt;as&lt;/code&gt; operator will make sure the target type is &lt;em&gt;compile-time&lt;/em&gt; compatible. &lt;/p&gt;

&lt;p&gt;If we want to verify this during &lt;em&gt;runtime&lt;/em&gt;, we should be using &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types"&gt;"type guards"&lt;/a&gt; for that. &lt;/p&gt;

&lt;p&gt;Thus, the lessons I've learnt are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Reading &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html"&gt;"Advanced Types"&lt;/a&gt; from the Handbook is a must.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave your #C baggage behind the closed door. There is no added runtime type system in JavaScript code that TypeScript would emit, and it won't magically make &lt;code&gt;instanceof&lt;/code&gt; work the way we might expect, coming from C#. A class object must be explicitly constructed with &lt;code&gt;new MyClass()&lt;/code&gt; syntax for &lt;code&gt;instanceof&lt;/code&gt; to work, and that's still a feature of JavaScript, not something specific to TypeScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use primitive basic types (&lt;code&gt;string&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;object&lt;/code&gt;) everywhere in TypeScript, and &lt;strong&gt;avoid using their class wrappers&lt;/strong&gt; (&lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt;, &lt;code&gt;Number&lt;/code&gt;, &lt;code&gt;Object&lt;/code&gt;), as a general rule.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you really need to test whether a particular variable or a property contains a string (boolean, number), &lt;code&gt;prop.constructor === String&lt;/code&gt; does work consistently for basic and wrapper types. When it is &lt;code&gt;true&lt;/code&gt;, you can go one step further and check if &lt;code&gt;typeof prop === "string"&lt;/code&gt;, to tell whether it's a basic type or a wrapper class.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that &lt;code&gt;prop.constructor === String&lt;/code&gt; may not work across realms (e.g., &lt;code&gt;iframes&lt;/code&gt;), but &lt;code&gt;prop.constructor.name === "String"&lt;/code&gt; will.&lt;/p&gt;

&lt;p&gt;I hope the above makes sense. Feel free to leave a comment here or on &lt;a href="https://twitter.com/noseratio"&gt;my Twitter&lt;/a&gt; if you disagree 🙂 &lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>types</category>
    </item>
    <item>
      <title>Thenable: how to make a JavaScript object await-friendly, and why it is useful</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Sat, 07 Nov 2020 11:09:44 +0000</pubDate>
      <link>https://dev.to/noseratio/we-can-make-any-javascript-object-await-able-with-then-method-1apl</link>
      <guid>https://dev.to/noseratio/we-can-make-any-javascript-object-await-able-with-then-method-1apl</guid>
      <description>&lt;h2&gt;
  
  
  What are thenables?
&lt;/h2&gt;

&lt;p&gt;This short post is to remind that we can add &lt;code&gt;.then(onFulfilled, onRejected)&lt;/code&gt; method to any JavaScript class or object literal, to make it play well with &lt;code&gt;await&lt;/code&gt;. It's useful when the object carries out asynchronous operations.&lt;/p&gt;

&lt;p&gt;Many C# developers are familiar with the concept of "custom awaiters" (see &lt;a href="https://devblogs.microsoft.com/pfxteam/await-anything/"&gt;"Await anything"&lt;/a&gt; by Stephen Toub). Interestingly, in JavaScript literally anything can be awaited as is (e.g., try &lt;code&gt;(await true) === true&lt;/code&gt;), but the language also offers a feature similar to C# awaitables: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#thenable_objects"&gt;&lt;em&gt;thenable objects&lt;/em&gt;&lt;/a&gt;, or &lt;em&gt;Thenables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Thenables are not promises, but they can be meaningfully used on the right side of the &lt;code&gt;await&lt;/code&gt; operator and are accepted by many standard JavaScript APIs, like &lt;a href="https://dev.torg/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve"&gt;&lt;code&gt;Promose.resolve()&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race"&gt;&lt;code&gt;Promise.race()&lt;/code&gt;&lt;/a&gt;, etc. For example, we can wrap a &lt;code&gt;thenable&lt;/code&gt; as a bona fide promise, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thenable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're interested in learning more about how it works behind the scene, the V8 blog got you covered: &lt;a href="https://v8.dev/blog/fast-async"&gt;"Faster async functions and promises"&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample use cases
&lt;/h2&gt;

&lt;p&gt;As a simple example to begin with, let's create a &lt;code&gt;Deffered&lt;/code&gt; object, inspired by &lt;a href="https://api.jquery.com/jquery.deferred"&gt;jQuery &lt;code&gt;Deferred&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=net-5.0"&gt;.NET &lt;code&gt;TaskCompletionSource&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createDeferred&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createDeferred&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// resolve the deferred in 2s &lt;/span&gt;
&lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;deferred&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For completeness, &lt;a href="https://gist.github.com/noseratio/da756d5bd1360cafa6eabc4d475a9ab7"&gt;the same in TypeScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, a little contrived but hopefully a more illustrative example, which shows how a &lt;code&gt;thenable&lt;/code&gt; can be useful for a proper resource cleanup (a timer in this case):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createStoppableTimer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;?.(),&lt;/span&gt;
    &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeout1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStoppableTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeout2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStoppableTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;timeout1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;timeout1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;timeout2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Surely, we could have just exposed &lt;code&gt;promise&lt;/code&gt; as a property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;timeout1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works, but I'm not a fan. I believe where &lt;code&gt;asyncWorkflow&lt;/code&gt; represents an asynchronous operation, we should be able to &lt;code&gt;await asyncWorkflow&lt;/code&gt; itself, rather than one of its properties. That's where implementing &lt;code&gt;asyncWorkflow.then(onFulfilled, onRejected)&lt;/code&gt; helps.&lt;/p&gt;

&lt;p&gt;Here is one more example of how to wait asynchronously for any arbitrary &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget"&gt;&lt;code&gt;EventTarget&lt;/code&gt;&lt;/a&gt; event, while cleaning up the event handler subscription properly. Here we're waiting for a popup window to be closed within the next 2 seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventObserver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;observeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;popup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStoppableTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;eventObserver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;eventObserver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="observeEvent"&gt;&lt;/a&gt;This is what the &lt;code&gt;observeEvent&lt;/code&gt; implementation may look like (note how it returns an object with &lt;code&gt;then&lt;/code&gt; and &lt;code&gt;close&lt;/code&gt; methods):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;observeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onevent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;?.(),&lt;/span&gt;
    &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// an async helper to wait for the event&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onevent&lt;/span&gt;&lt;span class="p"&gt;?.(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;?.();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;cleanup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;eventSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; 

      &lt;span class="nx"&gt;eventSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;once&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;eventPromise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      
    &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;?.();&lt;/span&gt;    
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use this pattern a lot, as it helps with properly structured error handling and scoped resources management. The errors are propagated from inside the event handler (if any) by rejecting the internal promise, so &lt;code&gt;await eventObserver&lt;/code&gt; will rethrow them. &lt;/p&gt;

&lt;p&gt;&lt;a id="TC39"&gt;&lt;/a&gt;As the current TC39 &lt;a href="https://github.com/tc39/proposal-explicit-resource-management"&gt;"ECMAScript Explicit Resource Management"&lt;/a&gt; proposal progresses, we soon should be able to do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventObserver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;observeEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;popup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;closed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStoppableTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventObserver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;eventObserver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will not have to call the cleanup methods explicitly. &lt;/p&gt;

&lt;p&gt;I my future blog posts, I hope to cover this and another important TC39 proposal by Ron Buckton — &lt;a href="https://github.com/tc39/proposal-cancellation"&gt;ECMAScript Cancellation&lt;/a&gt; — in more details, including what we could use today as alternatives. &lt;/p&gt;

&lt;p&gt;Thanks for reading! Feel free to leave a comment below or &lt;a href="https://twitter.com/noseratio"&gt;on Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>async</category>
      <category>await</category>
      <category>promise</category>
    </item>
    <item>
      <title>Would it make sense to have "Symbol.promise" as standard JavaScript Symbol?</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Thu, 22 Oct 2020 00:12:50 +0000</pubDate>
      <link>https://dev.to/noseratio/wouldn-t-it-be-nice-to-have-symbol-promise-as-standard-symbol-similar-to-symbol-asynciterator-410o</link>
      <guid>https://dev.to/noseratio/wouldn-t-it-be-nice-to-have-symbol-promise-as-standard-symbol-similar-to-symbol-asynciterator-410o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Updated&lt;/strong&gt;: I've tried to provide a better context for this discussion with my new post: &lt;a href="https://dev.to/noseratio/we-can-make-any-javascript-object-await-able-with-then-method-1apl"&gt;"Thenable: how to make a JavaScript object await-friendly, and why it is useful"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Asking for opinions. Would it make sense to have a standard symbol for the object's default awaitable, e.g. &lt;code&gt;Symbol.promise&lt;/code&gt;, by analog to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator"&gt;&lt;code&gt;Symbol.asyncIterator&lt;/code&gt;&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;I sometimes use the following pattern, in a nutshell (&lt;a href="https://codepen.io/noseratio/pen/eYzBBXp"&gt;codepen&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AsyncOperation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AsyncOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;completed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, because we've made an instance &lt;code&gt;AsyncOperation&lt;/code&gt; to be &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve"&gt;&lt;code&gt;thenable&lt;/code&gt;&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;If however we had &lt;code&gt;Symbol.promise&lt;/code&gt;, it'd be less boilerplate code for &lt;code&gt;AsyncOperation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;AsyncOperation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wouldn't &lt;code&gt;Symbol.promise&lt;/code&gt; be useful?&lt;/p&gt;

&lt;p&gt;Here is a less contrived snippet, adapted from some real-life code of mine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eventName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relevant part of &lt;code&gt;createSubscription&lt;/code&gt; code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd like to be able to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, I could as well just expose &lt;code&gt;promise&lt;/code&gt; as a property getter (and do &lt;code&gt;await subscription.promise&lt;/code&gt;), or as a method, similar to &lt;a href="https://www.learnrxjs.io/learn-rxjs/operators/utility/topromise"&gt;RxJS' &lt;code&gt;toPromise()&lt;/code&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Yet the same arguments could possibly be used for iterable objects, which nevertheless expose their iterators via [&lt;code&gt;Symbol.iterator&lt;/code&gt;] or [&lt;code&gt;Symbol.asyncIterator&lt;/code&gt;]. Not via something like &lt;code&gt;array.iterator&lt;/code&gt; or &lt;code&gt;array.getIterator()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;IMO, it'd be convenient if &lt;code&gt;await&lt;/code&gt; looked for &lt;code&gt;[Symbol.promise]&lt;/code&gt; in the same way the &lt;code&gt;for...of&lt;/code&gt; and &lt;code&gt;for await...of&lt;/code&gt; loops look for iterators.&lt;/p&gt;

&lt;p&gt;Given that &lt;strong&gt;we already can &lt;code&gt;await&lt;/code&gt; &lt;em&gt;any&lt;/em&gt; expression in JavaScript&lt;/strong&gt; (not just a &lt;code&gt;Promise&lt;/code&gt; or "thenable"), I think that would make sense.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Yet another OOP/C# person (me) trying to understand the mechanics behind React Hooks</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Wed, 30 Sep 2020 12:13:59 +0000</pubDate>
      <link>https://dev.to/noseratio/yet-another-oop-c-person-me-trying-to-understand-react-hooks-4aik</link>
      <guid>https://dev.to/noseratio/yet-another-oop-c-person-me-trying-to-understand-react-hooks-4aik</guid>
      <description>&lt;p&gt;I've written this article as a memo to my future self as well, and my goal was to make it short. If there is something here that isn't technically correct, a feedback would be appreciated.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the magic behind the simplicity of React Hooks?
&lt;/h3&gt;

&lt;p&gt;Coming to React from an OOP/MVVM/C# background, for a while I was having this "how-does-it-work-behind-the-scence" syndrome about React hooks. &lt;/p&gt;

&lt;p&gt;As they get called from what seemingly is a &lt;em&gt;plain, stateless JavaScript function&lt;/em&gt;, and yet hooks maintain their state.&lt;/p&gt;

&lt;p&gt;Particularly, about how multiple hooks of &lt;em&gt;the same kind&lt;/em&gt; coexist within &lt;em&gt;the same function component&lt;/em&gt; and persist their state across &lt;em&gt;multiple renders&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For example, across multiple invocations of the following &lt;code&gt;MyComponent&lt;/code&gt; function (&lt;a href="https://codepen.io/noseratio/pen/PoNvaav"&gt;try it in the CodePen&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;countUp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCountUp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;countDown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCountDown&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setCountUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    
    &lt;span class="nx"&gt;setCountDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rendering&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Up&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;refUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&amp;gt;&amp;lt;br/&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Down&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;refDown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&amp;gt;&amp;lt;br/&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Counts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;countUp&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;countDown&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&amp;gt;&amp;lt;br/&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;clicked&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How is it possible that &lt;em&gt;&lt;code&gt;refA.current&lt;/code&gt; and &lt;code&gt;refB.current&lt;/code&gt; can be mutated and still survive multiple renders, keeping their values&lt;/em&gt;, without relying upon something like JavaScript's &lt;code&gt;this&lt;/code&gt;? &lt;/p&gt;

&lt;p&gt;Especially, given they both were created with two identical invocations of &lt;code&gt;useRef(0)&lt;/code&gt;? My guts were telling me there should be a unique name parameter, like &lt;code&gt;useRef(0, "refA")&lt;/code&gt;, but there isn't.&lt;/p&gt;

&lt;p&gt;The same question applies to &lt;code&gt;countUp&lt;/code&gt;, &lt;code&gt;countDown&lt;/code&gt; and the corresponding &lt;code&gt;useState(0)&lt;/code&gt; calls which initialize these variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Something has got to maintain the state for us.
&lt;/h3&gt;

&lt;p&gt;And there has to be some kind of 1:1 mapping for each hook into that state. &lt;/p&gt;

&lt;p&gt;As it turns, there is no magic. In a nutshell, here is my understanding of how it goes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First of all, hook calls don't work outside React function components, by design. They implicitly rely upon the calling context React provides them with, when it renders the component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React maintains its own internal state for the life-time of the web page. While not exactly accurate, let's called it React's static state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each component like &lt;code&gt;MyComponent&lt;/code&gt; above has a dedicated entry in React's static state, and that entry keeps the state of each hook used by the component between renders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a hook like &lt;code&gt;useRef&lt;/code&gt; is called, React knows which component is calling it (the one currently being rendered), so React can retrieve that individual component's state entry it have previously mapped and stored in its static state. That's where the current values of hooks like &lt;code&gt;useRef&lt;/code&gt; and &lt;code&gt;useState&lt;/code&gt; are stored, per component. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initially, such entry gets created and mapped when the component gets mounted (or perhaps upon the first render, I didn't dig deep into that, but it's done once).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The exact order of calls like &lt;code&gt;useRef&lt;/code&gt; or &lt;code&gt;useState&lt;/code&gt; within the component function matters, and it should remain the same across subsequent renders. In our case, React initially creates two entries for &lt;code&gt;useRef&lt;/code&gt; in its internal state for &lt;code&gt;MyComponent&lt;/code&gt;, then two entries for &lt;code&gt;useState&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upon subsequent renders (invocations of &lt;code&gt;MyComponent&lt;/code&gt;), React knows how to access the correct state and which values to return, by the order of each &lt;code&gt;useRef&lt;/code&gt; or &lt;code&gt;useState&lt;/code&gt; call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'm not sure about exact data structure used by React to map hooks by the order of their appearance in the function component, I didn't dig into that either. But it's easy to think about the order of each hook call as of an index in the array of hooks maintained by React for the life cycle of our component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thus, if we mess about this order across multiple renders, our state will be broken, because the original indexing wouldn't be correct. E.g., the following made-up example will likely screw up the state of &lt;code&gt;refUp&lt;/code&gt; and &lt;code&gt;refDown&lt;/code&gt; very soon, because their order of &lt;code&gt;useRef&lt;/code&gt; calls is inconsistent: &lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
 &lt;span class="c1"&gt;// don't mess up the order of hooks like this:&lt;/span&gt;
 &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;refUp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;refDown&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;refUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;refDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt; 
 &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;refDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;refUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, &lt;em&gt;hooks are not available for class components&lt;/em&gt;. While in theory it might have been possible to support hooks for class components' &lt;code&gt;render()&lt;/code&gt; method, it's React's philosophy to keep the state in the class &lt;code&gt;this.state&lt;/code&gt; and use &lt;code&gt;this.setState()&lt;/code&gt; to update it, for class components.&lt;/p&gt;

&lt;p&gt;The following resources greatly helped me to understand these hook mechanics: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/facebook/react/blob/master/packages/react/src/ReactHooks.js"&gt;ReactHooks.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/hooks-rules.html"&gt;Rules of Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/hooks-faq.html#under-the-hood"&gt;Hooks FAQ - Under the Hood&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackernoon.com/deconstructing-the-magic-behind-react-hooks-33ca987e5307"&gt;Deconstructing the Magic Behind React Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/the-guild/under-the-hood-of-reacts-hooks-system-eb59638c9dba"&gt;Under the hood of React’s hooks system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://overreacted.io/why-do-hooks-rely-on-call-order/"&gt;Why Do React Hooks Rely on Call Order?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889"&gt;Making Sense of React Hooks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>hooks</category>
    </item>
    <item>
      <title>Why I no longer use ConfigureAwait(false)</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Thu, 17 Sep 2020 00:37:25 +0000</pubDate>
      <link>https://dev.to/noseratio/why-i-no-longer-use-configureawait-false-3pne</link>
      <guid>https://dev.to/noseratio/why-i-no-longer-use-configureawait-false-3pne</guid>
      <description>&lt;p&gt;This might be an unpopular opinion, but I'd like to share why I  no longer use &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; in pretty much any C# code I write, including libraries, unless required by the team coding standards.&lt;/p&gt;

&lt;p&gt;The following two points are widely seen as major benefits of calling &lt;code&gt;task.ConfigureAwait(false)&lt;/code&gt; and awaiting the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.configuredtaskawaitable"&gt;&lt;code&gt;ConfiguredTaskAwaitable&lt;/code&gt;&lt;/a&gt; value it returns, rather than the original &lt;code&gt;task&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Potential performance improvements&lt;/li&gt;
&lt;li&gt;Potential remedy for deadlocks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential performance improvements
&lt;/h2&gt;

&lt;p&gt;It might be the result of not queueing the &lt;code&gt;await&lt;/code&gt; continuation callbacks with the original synchronization context/task scheduler, but rather continuing in-place, on the same thread where the actual asynchronous operation has completed.&lt;/p&gt;

&lt;p&gt;In my opinion, &lt;strong&gt;this is much less relevant with the modern ASP.NET Core/ASP.NET 5+ backend&lt;/strong&gt;, which simply doesn't have a synchronization context by default anymore. &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; simply becomes a no-op in that execution environment.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;the front-end code normally does have a concept of the main UI thread&lt;/strong&gt;, with a certain UI framework-specific synchronization context installed on it (e.g, &lt;code&gt;DispatcherSynchronizationContext&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In this case, I believe that using &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; for the purpose of not continuing on a UI thread is a premature optimization, especially for small code chunks between awaits. Under particular circumstances, it may even have a negative effect, by introducing frequent yet redundant context switches. In a nutshell (contrived but illustrative):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;SomeAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;threadId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentManagedThreadId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// false: a redundant and probably undesired thread switch here&lt;/span&gt;
    &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;threadId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentManagedThreadId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MainForm_Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tcs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TaskCompletionSource&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;SomeAsync&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tcs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;tcs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetResult&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More details in my &lt;a href="https://stackoverflow.com/q/28410046/1768303"&gt;old related question on SO&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thus, for the UI threads, I prefer to explicitly control the execution context, especially where it is a part of performance-sensitive, CPU-intensive code.&lt;/p&gt;

&lt;p&gt;I can do that by either using &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=netcore-3.1#System_Threading_Tasks_Task_Run_System_Func_System_Threading_Tasks_Task__"&gt;&lt;code&gt;Task.Run(Func&amp;lt;Task&amp;gt; asyncFunc)&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RunOneWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RunAnotherWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, lately, with &lt;a href="https://gist.github.com/noseratio/5d2d5f2a0cbb71b7880ce731c3958e62"&gt;a custom implementation&lt;/a&gt; of &lt;code&gt;TaskScheduler.SwitchTo&lt;/code&gt; extension, inspired by &lt;a href="https://github.com/dotnet/runtime/issues/20025"&gt;this David Fowler's initiative&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;TaskScheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SwitchTo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RunOneWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RunAnotherWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RunOneWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;RunAnotherWorkflowAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The former two might be a bit more verbose and could incur an extra thread switch, but they clearly indicate the intent.&lt;/p&gt;

&lt;p&gt;Moreover, I don't have to worry about any side effects the current synchronization context/task scheduler may have on &lt;code&gt;RunOneWorkflowAsync&lt;/code&gt;, and whether or not the author of &lt;code&gt;RunOneWorkflowAsync&lt;/code&gt; used &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; internally in their implementation. &lt;/p&gt;

&lt;p&gt;With the second option, &lt;code&gt;TaskScheduler.Default.SwitchTo&lt;/code&gt; &lt;a href="https://gist.github.com/noseratio/5d2d5f2a0cbb71b7880ce731c3958e62#file-taskschedulerawaiter-cs-L53"&gt;is optimized&lt;/a&gt; to check if the current thread is already a &lt;code&gt;ThreadPool&lt;/code&gt; thread with the default task scheduler, and complete synchronously, if so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential remedy for deadlocks
&lt;/h2&gt;

&lt;p&gt;In my option, using &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; as a defensive measure against deadlock may actually hide obscure bugs. I prefer detecting deadlocks early. As a last resort, I'd still use &lt;code&gt;Task.Run&lt;/code&gt; as a wrapper for deadlock-prone code. Here is &lt;a href="https://stackoverflow.com/a/28445791/1768303"&gt;a real-life example&lt;/a&gt; of where I needed that. &lt;/p&gt;

&lt;p&gt;Moreover, from debugging and unit-testing prospective, we always have an option to install a custom &lt;code&gt;SynchronizationContext&lt;/code&gt; implementation for debugging asynchronous code, and that would also require to give up &lt;code&gt;ConfigureAwait(false)&lt;/code&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Microsoft's Stephen Toub in his excellent &lt;a href="https://devblogs.microsoft.com/dotnet/configureawait-faq/"&gt;"ConfigureAwait FAQ"&lt;/a&gt; still recommends using &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; for general-purpose, context-agnostic libraries, even if they only target .NET Core or later. Later in the comments to that blog post, &lt;a href="https://devblogs.microsoft.com/dotnet/configureawait-faq/#comment-4247"&gt;David Fowler mentions&lt;/a&gt; that &lt;em&gt;"most of ASP.NET Core doesn't use ConfigureAwait(false) and that was an explicit decision because it was deemed unnecessary."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use your own best judgment on whether you need it or not for a specific project. I've personally chosen to avoid &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; where possible, and control the execution context explicitly where it makes sense.&lt;/p&gt;

&lt;p&gt;I believe the library code should behave well in any context, and I don't like the idea of using &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; as a defensive remedy for undetected deadlocks. Performance-wise, where it is critical (like with ASP.NET Core), there is already no synchronisation context in modern .NET.&lt;/p&gt;

&lt;p&gt;As an added bonus, my C# code looks more clean without &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; all over the place :-)&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>async</category>
    </item>
    <item>
      <title>Comparing process working sets of WebView-based Windows Desktop apps</title>
      <dc:creator>Andrew Nosenko</dc:creator>
      <pubDate>Mon, 31 Aug 2020 13:21:12 +0000</pubDate>
      <link>https://dev.to/noseratio/comparing-process-working-sets-of-webview-based-windows-desktop-apps-5dkk</link>
      <guid>https://dev.to/noseratio/comparing-process-working-sets-of-webview-based-windows-desktop-apps-5dkk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Updated&lt;/strong&gt;, related discussion in &lt;a href="https://github.com/MicrosoftEdge/WebViewFeedback/issues/415#issuecomment-684133596"&gt;MicrosoftEdge Feedback repo&lt;/a&gt;. The source code repo with examples of each &lt;code&gt;WebView&lt;/code&gt;-based app mentioned here &lt;a href="https://github.com/noseratio/CompareWebViews"&gt;is now available&lt;/a&gt;, too. &lt;/p&gt;

&lt;p&gt;Let's compare the working sets of various WebView-based Windows Desktop apps. Each application simply loads &lt;a href="https://www.bing.com/"&gt;the Bing homepage&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Working set size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/noseratio/CompareWebViews/tree/main/IE11WebBrowserApp"&gt;Legacy IE11 WebBrowser WPF&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;164 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/noseratio/CompareWebViews/tree/main/WebView2App"&gt;MSEdge WebView2 WPF&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;582 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/noseratio/CompareWebViews/tree/main/ChromelyApp"&gt;Chromely/CefSharp&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;516 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/noseratio/CompareWebViews/tree/main/ElectronApp"&gt;Electron v10&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;570 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A screenshot of &lt;a href="https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer"&gt;Process Explorer&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3T1nOyxc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/noseratio/CompareWebViews/main/procexp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3T1nOyxc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/noseratio/CompareWebViews/main/procexp.jpg" alt="WebView working memory sets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Updated on 2021/05/27&lt;/strong&gt;: Prompted by &lt;a href="https://twitter.com/noseratio/status/1397542989891735555?s=20"&gt;this Twitter thread&lt;/a&gt;, I've re-verified the &lt;code&gt;WPF&lt;/code&gt; + &lt;code&gt;WebView2&lt;/code&gt; memory footprint with &lt;a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section"&gt;now-GA WebView2 Runtime&lt;/a&gt; (v90.0.818.66),  &lt;a href="https://www.nuget.org/packages/Microsoft.Web.WebView2"&gt;&lt;code&gt;Microsoft.Web.WebView2&lt;/code&gt;&lt;/a&gt; (v1.0.818.41) and &lt;a href="https://dotnet.microsoft.com/download/dotnet/5.0"&gt;.NET 5&lt;/a&gt; (v5.0.6).  &lt;/p&gt;

&lt;p&gt;I witness an amazing improvement, ~270MB now vs ~580MB I saw back in August 2020 when &lt;code&gt;WebView2&lt;/code&gt; was in preview:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1lXMrkfa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9b6aj43l4k6o7wt1psf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1lXMrkfa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9b6aj43l4k6o7wt1psf.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code is &lt;a href="https://github.com/noseratio/CompareWebViews/tree/net5-webview2-90/WebView2App"&gt;here&lt;/a&gt;. Well done &lt;a href="https://twitter.com/MSEdgeDev"&gt;@MSEdgeDev&lt;/a&gt; team!&lt;/p&gt;

</description>
      <category>windows</category>
      <category>desktop</category>
      <category>electron</category>
      <category>webview2</category>
    </item>
  </channel>
</rss>
