<?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: Hem</title>
    <description>The latest articles on DEV Community by Hem (@hem).</description>
    <link>https://dev.to/hem</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%2F177695%2Ff572eff5-b4bd-462a-9a7a-7b6f1811752d.png</url>
      <title>DEV Community: Hem</title>
      <link>https://dev.to/hem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hem"/>
    <language>en</language>
    <item>
      <title>🔑 OAuth 2.0 flows explained in GIFs</title>
      <dc:creator>Hem</dc:creator>
      <pubDate>Tue, 14 Jul 2020 05:46:03 +0000</pubDate>
      <link>https://dev.to/hem/oauth-2-0-flows-explained-in-gifs-2o7a</link>
      <guid>https://dev.to/hem/oauth-2-0-flows-explained-in-gifs-2o7a</guid>
      <description>&lt;p&gt;In this post, we will be covering all OAuth 2.0 flows using GIFs that are simple and easier to understand. This post can be used as a cheat-sheet for future reference as well! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Feel free to ⏩ skip to the flows directly if you are already aware of OAuth.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Hold on, what's OAuth❓
&lt;/h2&gt;

&lt;p&gt;OAuth (Open Authorization) enables third-party websites or apps to access user's data without requiring them to share their credentials. It is a set of rules that makes access delegation possible. The user gets to &lt;em&gt;authorize&lt;/em&gt; which resources an app can access and limits access accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminologies 🧱
&lt;/h2&gt;

&lt;p&gt;Now that we know what OAuth is about, let us quickly cover the terminologies before we dive-in. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Client 📦&lt;/td&gt;
&lt;td&gt;The application that seeks access to resources. Usually the third-party.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource Owner 👤&lt;/td&gt;
&lt;td&gt;The user who owns the resources. It can also be a machine 🤖 (E.g. Enterprise scenarios).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource 🖼&lt;/td&gt;
&lt;td&gt;Could be images, data exposed via APIs, and so on.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource Server 📚&lt;/td&gt;
&lt;td&gt;Server that hosts protected resources. Usually, an API server that serves resources if a proper token is furnished.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization Server 🛡&lt;/td&gt;
&lt;td&gt;Server responsible for authorizing the client and issuing access tokens.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User-Agent 🌐&lt;/td&gt;
&lt;td&gt;The browser or mobile application through which the resource owner communicates with our authorization server.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Access Token 🔑&lt;/td&gt;
&lt;td&gt;A token which is issued as a result of successful authorization. An access token can be obtained for a set of permissions (scopes) and has a pre-determined lifetime after which it expires.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refresh Token 🔄&lt;/td&gt;
&lt;td&gt;A special type of token that can be used to replenish the access token.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now, let us relate these terminologies in an abstract OAuth flow based on an example &lt;a href="https://tools.ietf.org/html/rfc6749#section-1" rel="noopener noreferrer"&gt;(1)&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An end-user (resource owner 👤) grants a printing service (app 📦) access to their photo (resource 🖼) hosted in a photo-sharing service (resource server 📚), without sharing their username and password. Instead, they authenticate directly with a server trusted by the photo-sharing service (authorization server 🛡), which issues the printing service delegation-specific credentials (access token 🔑).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note that our app (client) has to be &lt;em&gt;registered&lt;/em&gt; in the authorization server in the first place. A Client ID is returned as a result. A client secret is also optionally generated depending on the scenario. This secret is known only to the authorization server and the application.&lt;/p&gt;

&lt;p&gt;Okay, enough theory! It is time for some GIFs to understand the authorization scenarios/flows!&lt;/p&gt;




&lt;h2&gt;
  
  
  Flows in OAuth 2.0 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Authorization Code Grant&lt;/li&gt;
&lt;li&gt;
Authorization Code Grant with PKCE

&lt;ul&gt;
&lt;li&gt;Code Transformation Method (CM) - Meet SHA256&lt;/li&gt;
&lt;li&gt;Code verifier (CV) &amp;amp; Code Challenge (CC)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Client Credentials Grant&lt;/li&gt;
&lt;li&gt;Resource Owner Password Credentials Grant&lt;/li&gt;
&lt;li&gt;Implicit Grant&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  1. Authorization Code Grant flow  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It is a popular browser-based authorization flow for Web and mobile apps. You can directly relate it with the above-mentioned example. In the diagram below, the flow starts from the Client redirecting the user to the authorization endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2j7kqc7qabtfpl250jf2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2j7kqc7qabtfpl250jf2.gif" alt="1 Authorization Code Grant Flow - confidential clients"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This flow is optimized for &lt;em&gt;confidential clients&lt;/em&gt;. Confidential clients are apps that can guarantee the secrecy of &lt;code&gt;client_secret&lt;/code&gt;. A part of this flow happens in the front-channel (until the authorization code is obtained). As you can see, the &lt;code&gt;access_token&lt;/code&gt; 🔑 exchange step happens confidentially via back-channel (server-to-server communication). &lt;/p&gt;

&lt;p&gt;Now you might naturally wonder, 'What about public clients?!'&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Authorization Code Grant with PKCE  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Public clients using authorization code grant flow have security concerns. Be it single-page JS apps or native mobile apps, it is impossible to hide the &lt;code&gt;client_secret&lt;/code&gt; as the entire source is accessible (via DevTools or App Decompilation). Also, in native apps where there is a custom URI scheme, there is a possibility of malicious apps intercepting the authorization code via similar redirect URIs.&lt;/p&gt;

&lt;p&gt;To tackle this, the Authorization Code Grant flow makes use of Proof Key for Code Exchange (PKCE). This enables the generation of a secret at runtime which can be safely verified by the Authorization Server. So how does this work?&lt;/p&gt;

&lt;h4&gt;
  
  
  2.1. Transformations - Meet SHA256  &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Basically the client generates a random string named &lt;code&gt;Code Verifier&lt;/code&gt; (CV). A &lt;code&gt;Code transformation method&lt;/code&gt; (CM) is applied to the CV to derive a &lt;code&gt;Code Challenge&lt;/code&gt; (CC) ✨ As of now, there are two transformation methods &lt;code&gt;plain&lt;/code&gt; or &lt;code&gt;S256&lt;/code&gt; (SHA-256)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftw9nu7l1yufx3bczy7fi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftw9nu7l1yufx3bczy7fi.gif" alt="2.1 Authorization Code Grant Flow - PKCE - How does SHA256 work?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In plain transformation, CC will be equal to CV. This is not recommended for obvious security reasons &amp;amp; hence S256 is recommended. SHA256 is a hash function. On a high-level, it takes input data and outputs a string. However, there are special characteristics to this output string:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This string is unique to the input data and any change in the input will result in a different output string! One can say, it is a signature of the input data.&lt;/li&gt;
&lt;li&gt;The input data &lt;em&gt;cannot&lt;/em&gt; be recovered from the string and it is a one-way function (Refer the GIF above).&lt;/li&gt;
&lt;li&gt;The output string is of fixed-length.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2.2. How do we generate the Code Challenge (CC) from the Code verifier (CV) ?  &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftfuwug010zprz84p702o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftfuwug010zprz84p702o.gif" alt="2.2 Authorization Code Grant Flow - PKCE - What is a Code Challenge vs. Code Verifier"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might have already guessed it. Take a look at the diagram to understand how CC is generated from CV. In this case, since SHA256 is used, CV cannot be generated from CC (Remember, it is a one-way transformation). Only CC can be generated from CV (Given that the transformation method is known - &lt;code&gt;S256&lt;/code&gt; in our case).&lt;/p&gt;

&lt;h4&gt;
  
  
  PKCE flow
&lt;/h4&gt;

&lt;p&gt;Note that the flow starts with CV and CC generated first replacing the &lt;code&gt;client_secret&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fodkf14kzlb5gcbvrmuvx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fodkf14kzlb5gcbvrmuvx.gif" alt="Authorization Code Grant with PKCE "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know how CV, CC is generated, let us take a look at the complete flow. Most parts are similar to the authorization code grant flow. The CV and CC are generated even before the flow starts. Initially, only the CC and CM are passed to obtain an authorization code. Once the authorization code is obtained, the CV is sent along to obtain the access token. &lt;/p&gt;

&lt;p&gt;In order for the authorization server to confirm the legitimacy, it applies the transformation method (CM, which is SHA256) on the received CV and compares it with the &lt;em&gt;previously-obtained&lt;/em&gt; CC. If it matches, a token is provided! Note that even if someone intercepts the authorization code, they will not have the CV. Thanks to the nature of the one-way function, a CV cannot be recovered from CC. Also, CV cannot be found from the source or via decompilation as it is only generated during runtime!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Client Credentials Grant flow &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the above flows, a resource owner (user) had to provide consent. There can also be scenarios where a user's authorization is not required every time. Think of machine-to-machine communication (or app-to-app). In this case, the client is confidential by nature and the apps may need to act on behalf of themselves rather than that of the user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgp4n79x84xujj8mn625w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgp4n79x84xujj8mn625w.gif" alt="4 Client Credentials Grant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, this is the simplest of all flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Resource Owner Password Credentials Grant flow &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This flow is to be used only when there is a &lt;em&gt;high degree of trust&lt;/em&gt; between the resource owner and the client. As you can see, initially, the username &amp;amp; password is obtained from the R.O and are used to fetch the &lt;code&gt;access_token&lt;/code&gt;. The username &amp;amp; password details will be discarded once the token is obtained. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6hsfukc7f4rnopbsy04f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6hsfukc7f4rnopbsy04f.gif" alt="3 Resource Owner Password Credentials grant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This flow is &lt;em&gt;not recommended&lt;/em&gt; for modern applications and is often only used for legacy or migration purposes. It carries high risk compared to other flows as it follows the password anti-pattern that OAuth wants to avoid in the first place!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Implicit Grant flow &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This flow is &lt;em&gt;no longer recommended&lt;/em&gt; officially! Implicit grant was considered an alternative to Authorization Code Grant for public clients. As you can notice, the public client does not contain the &lt;code&gt;client_secret&lt;/code&gt; and there is no back-channel involved. In fact, the access token is obtained immediately after the consent is obtained.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F90t3te63144tcdven41w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F90t3te63144tcdven41w.gif" alt="5 Implicit Grant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the token is passed in the URL fragment (Begins with &lt;code&gt;#&lt;/code&gt;) which will never be sent over the network to the redirect URL. Instead, the fragment part is accessed by a script that is loaded in the frontend (as a result of redirection). The &lt;code&gt;access_token&lt;/code&gt; will be extracted in this manner and subsequent calls are made to fetch the resources. As you can already see, this flow is susceptible to access token leakage and replay attacks. &lt;/p&gt;

&lt;p&gt;It is &lt;a href="https://tools.ietf.org/html/draft-ietf-oauth-security-topics-09#section-2.1.2" rel="noopener noreferrer"&gt;recommended&lt;/a&gt; to use the Authorization Code Grant or any other suitable grant types instead of Implicit.&lt;/p&gt;




&lt;p&gt;Hope this post was useful. Checkout &lt;a href="https://tools.ietf.org/html/rfc6749" rel="noopener noreferrer"&gt;RFC 6749&lt;/a&gt;, &lt;a href="https://tools.ietf.org/html/rfc6749" rel="noopener noreferrer"&gt;RFC 7636&lt;/a&gt; to dig deeper into the steps involved in each of the flows.&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts as well. Don't forget to share this post if you found it useful 🚀&lt;/p&gt;

&lt;p&gt;Let me know what you would like to see next as a part of the GIF series! Until then, stay OAuthsome!✨&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://twitter.com/HemSays" rel="noopener noreferrer"&gt;🐥 Twitter&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.linkedin.com/in/hems23/" rel="noopener noreferrer"&gt;💼 LinkedIn&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




</description>
      <category>oauth</category>
      <category>security</category>
      <category>computerscience</category>
      <category>design</category>
    </item>
    <item>
      <title>👩‍💻👨‍💻Running a Highly Engaging Virtual Developer Event</title>
      <dc:creator>Hem</dc:creator>
      <pubDate>Mon, 18 May 2020 06:10:03 +0000</pubDate>
      <link>https://dev.to/hem/running-a-highly-engaging-virtual-developer-event-aaj</link>
      <guid>https://dev.to/hem/running-a-highly-engaging-virtual-developer-event-aaj</guid>
      <description>&lt;ul&gt;
&lt;li&gt;How do you run technical sessions without participants dozing over the monologue of the presenter? &lt;/li&gt;
&lt;li&gt;How do you ensure that the participation rate doesn't drop hard like Skrillex beats on the second day of the event?&lt;/li&gt;
&lt;li&gt;How do you maintain the liveliness of an in-person event without running into the territory of graveyard silence?
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3wf7yHu---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/19341550/82094206-3ad1e700-971a-11ea-9ff7-715ff155d8e8.jpg" alt="This is me planning the event|400" width="600" height="483"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, honestly, we didn't know the answers either. All that we knew was that we had some exciting announcements for our developers. We huddled together and worked our way through these questions, leading to our first-ever virtual developer event.&lt;/p&gt;

&lt;p&gt;Here are a few things that worked out really well:&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣ Developers love features, but more so when it's feedback-driven:
&lt;/h2&gt;

&lt;p&gt;Freshuddle&lt;a href="https://community.developers.freshworks.com/t/freshworks-developers-unite-freshhuddle-is-back/343"&gt;🔗&lt;/a&gt;, being a developer event, had a lot of feature announcements and platform updates. The interesting thing? Almost half of the features manifested from developer feedback (Well, so did the tickets, but that's a story for another day😸). Talking about what we did for developers based on what they have asked for is a &lt;em&gt;strong hook&lt;/em&gt;. It captures their attention and invests their mind into anything that follows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a rule of thumb, we start with insights from the previous event and proceed with an overview of the brand-new features that were derived from them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ We made it easier for developers to share feedback online and offline. We have a dedicated developer forum, 'Connect with DevRel' program, and Partner talk sessions so that developers can reach out to us comfortably.&lt;/p&gt;

&lt;p&gt;✅ Valid feedbacks are tracked from the source, consistently, until it reaches the right team. Updates are shared with the developers during events or via forums, completing the feedback loop. We try to under-commit and over-deliver.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;💡 There is also an exciting announcement at the end of this post for startups, independent developers, and aspiring students. Stay tuned!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2️⃣ Why game the system when the system can be a game?
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;br&gt;
As I said earlier, we didn't start with a perfect plan. However, we wanted to ensure that the participants felt engaged and included during each session. In fact, we themed these sessions like a game so that nobody gets bored! The participants were able to interact and live-code with the presenters during the demos.&lt;br&gt;
Liquid error: internal&lt;/p&gt;

&lt;p&gt;✅ Every session had live interactions. Collaboration tools such as Glitch, Mentimeter, and Kahoot proved to be immensely useful. Quizzes were interwoven with the content on-screen to make it highly engaging. This technique was so powerful that we maintained an audience retention rate close to 96% over 2 days&lt;/p&gt;

&lt;p&gt;✅ Quizzes and polls started very light and gradually proceeded to be highly relevant to the sessions. Participants were rewarded for listening and getting the answers right. This enabled us to not only have fun but also to strengthen content absorption! (Also, It helped me with Netflix series recommendations 😅)&lt;br&gt;
&lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s88ok-CK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EYEdJxLVAAAF9UA.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pg_F6TAp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1251179360716906496/ZZof5Nke_normal.png" alt="Hem profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Hem
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @hemsays
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      We took a quick break and stretched out for the `Design Exercise` session. Guess who was the presenter? &lt;br&gt;&lt;br&gt;Me 🥳! And yes, I did start with sourcing Netflix series recommendations 😅&lt;br&gt;&lt;br&gt;We also ran a rapid-fire quiz to reward our participants at the end of the session 🏆 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      15:43 PM - 15 May 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1261321432430084097" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1261321432430084097" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1261321432430084097" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;
&lt;br&gt;
✅ Making the best use of tools at our disposal was essential. We made use of Zoom and took complete advantage of the capabilities that it offered - Breakout rooms, Webinars, Chat, and audio share. Orchestrating them worked wonders.
&lt;h2&gt;
  
  
  3️⃣ Collaborative coding is a thriller! It is almost a sport:
&lt;/h2&gt;

&lt;p&gt;Having delighted the developers, it would be unfair to lower the bar later on. Thanks to Glitch, Freshworks Developer Kit (FDK) was made collaboration-ready back in 2019 itself. In no time, almost all the participants jumped into the live editor and started developing the app, in parallel. &lt;/p&gt;

&lt;p&gt;Yes, you heard it right, &lt;em&gt;in parallel&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;✅ The App development setup was moved online making it easy for people to start coding right away. We saved a ton of time by moving the Freshworks Developer Kit to Glitch so that people don't have to spend time setting things up.&lt;/p&gt;

&lt;p&gt;✅ Collaborative coding turns out to be more adventurous than quizzes. We defined what needs to be done before the start of the demo and participants hacked their way into getting it right! At one point, it became as entertaining as watching football.&lt;/p&gt;

&lt;p&gt;All of this productivity was possible because we ensured near-zero time-to-value. Simply put, Time-to-value (TTV) is the time taken to achieve something useful.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a product or platform can offer value to the developers in a really short time, it is a sure-shot sign of success.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2_LBg5qf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1261321494363168769/pu/img/Anahe8vW1LFXZqIH.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pg_F6TAp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1251179360716906496/ZZof5Nke_normal.png" alt="Hem profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Hem
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @hemsays
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Next up, we had &lt;a href="https://twitter.com/rohithjayaraman"&gt;@rohithjayaraman&lt;/a&gt; presenting &lt;a href="https://twitter.com/freshcaller"&gt;@freshcaller&lt;/a&gt;  app development! He put on a great show with one of the seasoned platform developers - Ilya &lt;a href="https://twitter.com/belyavskiy"&gt;@belyavskiy&lt;/a&gt;. The duo made live coding as interesting as a football game! &lt;br&gt;&lt;br&gt;🍿Next time, I am grabbing some popcorn! 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      15:44 PM - 15 May 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1261321662974193664" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1261321662974193664" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1261321662974193664" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;We also tried collaborative solutioning through Excalidraw (live whiteboard) where we worked on design challenges together with the participants. We had a Design Excercise session where participants collectively solved and arrived on solutions for app scalability challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  4️⃣ Putting developers on the spotlight:
&lt;/h2&gt;

&lt;p&gt;Recognizing developers for their efforts and celebrating them inspires great work. Passionate developers are a rare breed. If we aren't paying enough attention to them, they will most likely lose their enthusiasm. This is literally the last thing that anyone would want in a growing community.&lt;/p&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;✅ Many of our partners were invested in the initiatives and the early access programs that we rolled out before the event. We ensured to recognize their work and reward them with goodies.&lt;/p&gt;

&lt;p&gt;✅ Similarly, we also opened the stage for partner developer talks. Historically, we have had talks lasting for more than the allotted time because fellow developers could easily relate to challenges and approaches to solve the same. This also evoked a strong sense of community.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pg_F6TAp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1251179360716906496/ZZof5Nke_normal.png" alt="Hem profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Hem
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @hemsays
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      We open up the stage for developer talks. Akshay Kulkarni &amp;amp; Alisha from &lt;a href="https://twitter.com/Artissol_inc"&gt;@Artissol_inc&lt;/a&gt; present an amazing session on how they made the best use of platform features and product REST APIs in their app 👏
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      15:44 PM - 15 May 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1261321689813536770" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1261321689813536770" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1261321689813536770" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  5️⃣ Teamwork is everything:
&lt;/h2&gt;

&lt;p&gt;All of this good work wouldn't have been possible without a great team. We were able to apply what we learned from the past. We were provided with enough space to experiment. This ensured we were data-informed and strategy-driven.&lt;/p&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;✅ Almost everything that we learn or discover is documented. Similarly, we retrospect on the events and document key findings and insights. There is a free flow of knowledge within the team.&lt;/p&gt;

&lt;p&gt;✅ Being empathetic is a key trait of DevRels. This is extremely important when it comes to events as well. We view things from the perspective of developers and our coworkers. This aids in quality decision-making. It is important to note that being empathetic does not mean agreeing to everything. We have a healthy &amp;amp; constructive level of critique as well.&lt;/p&gt;




&lt;p&gt;Now, that being said, as I promised earlier, I have an interesting announcement for independent developers, startups, and students who are willing to benefit from the Freshworks App ecosystem 👇&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GD927L0q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EYEddOEUwAAnbwb.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pg_F6TAp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1251179360716906496/ZZof5Nke_normal.png" alt="Hem profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Hem
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @hemsays
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Developers, Students &amp;amp; Startups can benefit from the Freshworks ecosystem through co&amp;lt;div/&amp;gt; and can potentially kick-start their future businesses.&lt;br&gt;&lt;br&gt;You can reach out to me, &lt;a href="https://twitter.com/Saif_Shines"&gt;@Saif_Shines&lt;/a&gt;, or &lt;a href="https://twitter.com/juhi_singh15"&gt;@juhi_singh15&lt;/a&gt; for further details. 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      15:45 PM - 15 May 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1261321766162456577" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1261321766162456577" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1261321766162456577" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;In light of the current situation, we wanted to empower developers who are willing to learn and build powerful apps for Freshworks products. In a way, we wanted to turn the COVID situation on its head - Making it an opportunity. Hence, &lt;code&gt;co&amp;lt;div/&amp;gt;&lt;/code&gt; 🥳. We are also having a hackathon at the end of the program ♥️. If you are interested, feel free to check it out!&lt;/p&gt;




&lt;p&gt;Hope you found this article useful. I will keep you posted on our future DevRel adventures as well. Also, I am open to hearing your thoughts on what worked out in your virtual event too!&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>webdev</category>
      <category>eventsinyourcity</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🐨🎤[GIF] Cheatsheet for Javascript Nullish Coalescing operator</title>
      <dc:creator>Hem</dc:creator>
      <pubDate>Mon, 20 Jan 2020 11:18:09 +0000</pubDate>
      <link>https://dev.to/hem/gif-cheatsheet-for-javascript-nullish-coalescing-operator-5537</link>
      <guid>https://dev.to/hem/gif-cheatsheet-for-javascript-nullish-coalescing-operator-5537</guid>
      <description>&lt;p&gt;Good day folks! 👋 Today, we are going to cover something small, yet, an important feature in Javascript. In this post, we will see how &lt;code&gt;Nullish Coalescing&lt;/code&gt; or Nullish Koala-sing 🐨🎤 (whichever sounds good 😅) works using GIFs.&lt;/p&gt;

&lt;p&gt;👇&lt;em&gt;Things to note before we get started:&lt;/em&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Short-circuiting is denoted by &lt;code&gt;⚡️&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;At the time of writing this post, Nullish Coalescing was a &lt;a href="https://github.com/tc39/proposal-nullish-coalescing"&gt;&lt;code&gt;Stage 4&lt;/code&gt;&lt;/a&gt; proposal&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alright, let's get started with the different scenarios of its usage &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 1 (Base case)&lt;/em&gt;:  If the expression at the &lt;code&gt;left-hand side&lt;/code&gt; of the &lt;code&gt;??&lt;/code&gt; operator evaluates to &lt;code&gt;undefined&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt;, its &lt;code&gt;right-hand side&lt;/code&gt; is returned.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_r7njjRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72685059-487cb480-3b0c-11ea-9948-463070e500dd.gif" class="article-body-image-wrapper"&gt;&lt;img alt="If the expression at the  raw `left-hand side` endraw  of the  raw `??` endraw  operator evaluates to  raw `undefined` endraw  or  raw `null` endraw , its  raw `right-hand side` endraw  is returned." src="https://res.cloudinary.com/practicaldev/image/fetch/s--_r7njjRJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72685059-487cb480-3b0c-11ea-9948-463070e500dd.gif" width="880" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 2&lt;/em&gt;: Behavior of Nullish Coalescing &lt;code&gt;??&lt;/code&gt; operator with &lt;code&gt;falsy&lt;/code&gt; Javascript values.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--199Pu2tX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72626449-bd1aec00-3970-11ea-908a-e23b56f5f33a.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Behavior of Nullish Coalescing  raw `??` endraw  operators when  raw `falsy` endraw  Javascript values are passed " src="https://res.cloudinary.com/practicaldev/image/fetch/s--199Pu2tX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72626449-bd1aec00-3970-11ea-908a-e23b56f5f33a.gif" width="880" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how short-circuiting (denoted by ⚡️) happens when the LHS is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. It doesn't matter if the LHS is falsy values &lt;em&gt;except&lt;/em&gt; for &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: Explicit &lt;em&gt;parentheses groups&lt;/em&gt; are required to mix with &lt;code&gt;||&lt;/code&gt; and &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Scenario 3&lt;/em&gt;: When mixed with other short-circuiting operators &lt;code&gt;||&lt;/code&gt; and &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; &lt;em&gt;without&lt;/em&gt; parentheses&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--arUZu8mR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72658820-91cde680-39dc-11ea-897d-73be34a174c0.gif" class="article-body-image-wrapper"&gt;&lt;img alt="When mixed with other short-circuiting operators  raw `||` endraw  and  raw `&amp;amp;&amp;amp;` endraw  *without* parentheses logical or and logical and javascript" src="https://res.cloudinary.com/practicaldev/image/fetch/s--arUZu8mR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72658820-91cde680-39dc-11ea-897d-73be34a174c0.gif" width="880" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 4&lt;/em&gt;: When mixed with other short-circuiting operators &lt;code&gt;||&lt;/code&gt; and &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; &lt;em&gt;with&lt;/em&gt; parentheses groups&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cS6sKBHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72658821-91cde680-39dc-11ea-80db-5e160724f25c.gif" class="article-body-image-wrapper"&gt;&lt;img alt="When mixed with other short-circuiting operators  raw `||` endraw  and  raw `&amp;amp;&amp;amp;` endraw  *with* parentheses groups" src="https://res.cloudinary.com/practicaldev/image/fetch/s--cS6sKBHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72658821-91cde680-39dc-11ea-80db-5e160724f25c.gif" width="880" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9yc1rx41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72658822-91cde680-39dc-11ea-9788-29b89b5f4b96.gif" class="article-body-image-wrapper"&gt;&lt;img alt="When mixed with other short-circuiting operators  raw `||` endraw  and  raw `&amp;amp;&amp;amp;` endraw  *with* parentheses groups" src="https://res.cloudinary.com/practicaldev/image/fetch/s--9yc1rx41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/19341550/72658822-91cde680-39dc-11ea-9788-29b89b5f4b96.gif" width="880" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it for today and I hope you found it useful!&lt;/p&gt;

&lt;p&gt;And hey, I ❤️ learning from and staying in touch with the curious folks out there (I'm looking at you. Yeah, YOU!). So, please feel free to reach out if you have any questions or suggestions 🙋‍♀️🙋‍♂️ I'm all ears 🤩&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://twitter.com/HemSays"&gt;🐥Twitter&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.linkedin.com/in/hems23/"&gt;💼LinkedIn&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Auf wiedersehen 🙌🏼&lt;/p&gt;



&lt;p&gt;Repo Link : &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/hemchander23"&gt;
        hemchander23
      &lt;/a&gt; / &lt;a href="https://github.com/hemchander23/javascript_in_gifs"&gt;
        javascript_in_gifs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Javascript concepts and features visualised in the form of GIFS. I use it for my own reference. Glad if it was useful for you !
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Javascript in GIFs 🎉
&lt;/h1&gt;
&lt;p&gt;Do you find the documentation hard to understand ? Worry no more, the GIFs got you covered!&lt;/p&gt;
&lt;h2&gt;
Contents&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/hemchander23/javascript_in_gifspromise_api"&gt;Promise API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hemchander23/javascript_in_gifsnullish_coalescing"&gt;Nullish Coalescing&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Feel free to contribute ❤️&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/hemchander23/javascript_in_gifs"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>javascript</category>
      <category>design</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>🚀 [GIF] Cheatsheet for Javascript Promise API methods - Promise.all, Promise.allSettled, Promise.race, Promise.any</title>
      <dc:creator>Hem</dc:creator>
      <pubDate>Mon, 13 Jan 2020 12:57:36 +0000</pubDate>
      <link>https://dev.to/hem/gif-cheatsheet-for-javascript-promise-api-methods-promise-all-promise-allsettled-promise-race-promise-any-1l2o</link>
      <guid>https://dev.to/hem/gif-cheatsheet-for-javascript-promise-api-methods-promise-all-promise-allsettled-promise-race-promise-any-1l2o</guid>
      <description>&lt;p&gt;Hello everybody 👋! I created this GIF cheatsheet for my own reference and I hope it will be useful for the community as well ❤️&lt;/p&gt;

&lt;h3&gt;
  
  
  Index
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How is this organized?&lt;/li&gt;
&lt;li&gt;
Promise.resolve,Promise.reject
&lt;/li&gt;
&lt;li&gt;Promise.all&lt;/li&gt;
&lt;li&gt;Promise.allSettled&lt;/li&gt;
&lt;li&gt;Promise.race&lt;/li&gt;
&lt;li&gt;Promise.any&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  How is this organized? &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Consider the GIFs like watching a slow-mo video of Promise API methods in action. The scenarios for each Promise API describe how they work with an emphasis on Promise status transition, value/reasons, and the order.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Color Code&lt;/th&gt;
&lt;th&gt;Promise Status&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img alt="pending" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72203681-cdc0f300-3494-11ea-843e-4b4ce3e7911f.png"&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pending&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Represents initial state. The operation represented by the promise is neither fulfilled or rejected.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img alt="fulfilled" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72203680-cd285c80-3494-11ea-8d6c-b3bb1e52d0fe.png"&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fulfilled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Operation is successful and result &lt;em&gt;value&lt;/em&gt; is assigned. Typically, values appear on top of the respective promises upon fulfillment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img alt="rejected" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72203682-cdc0f300-3494-11ea-99eb-40dec7737d60.png"&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rejected&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Operation unsuccesful and usually there is a &lt;em&gt;reason&lt;/em&gt; for rejection. It appears on top of the rejected promise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For the sake of simplicity, I have added numbers below each promise representing the order in which they settle. This is handy while understanding the &lt;em&gt;short-circuiting&lt;/em&gt; behavior (denoted by ⚡️) of each promise API. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;Promise.resolve&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Scenario 1&lt;/em&gt;: If the given value is &lt;em&gt;not&lt;/em&gt; a &lt;code&gt;thenable&lt;/code&gt; but a &lt;em&gt;valid&lt;/em&gt; Javascript &lt;code&gt;value&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240446-2ebe0780-360a-11ea-8e8c-e6b0c9b9f20a.gif" class="article-body-image-wrapper"&gt;&lt;img alt="If the given value is _not_ a  raw `thenable` endraw  but a _valid_ Javascript  raw `value` endraw " src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240446-2ebe0780-360a-11ea-8e8c-e6b0c9b9f20a.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 2&lt;/em&gt;: If the given value is a &lt;code&gt;thenable&lt;/code&gt; (i.e., Promise or object with &lt;code&gt;then()&lt;/code&gt; method&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240447-2f569e00-360a-11ea-8a63-25a3920da75d.gif" class="article-body-image-wrapper"&gt;&lt;img alt="If the given value is a  raw `thenable` endraw  (i.e., Promise or object with  raw `then()` endraw  method" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240447-2f569e00-360a-11ea-8a63-25a3920da75d.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 3&lt;/em&gt;: &lt;em&gt;Nested&lt;/em&gt; Promise-like objects&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240448-2f569e00-360a-11ea-806c-2b283119374a.gif" class="article-body-image-wrapper"&gt;&lt;img alt="_Nested_ Promise-like objects" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240448-2f569e00-360a-11ea-806c-2b283119374a.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;Promise.reject&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Scenario&lt;/em&gt;: Rejection with a &lt;code&gt;reason&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240449-2f569e00-360a-11ea-82e5-ae18cd4155f0.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Rejection with a  raw `reason` endraw " src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72240449-2f569e00-360a-11ea-82e5-ae18cd4155f0.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;Promise.all&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Scenario 1&lt;/em&gt;: All passed-in Promises get fulfilled&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202910-f3e19580-348a-11ea-8a00-49c005f3cdd3.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.all - All passed-in Promises get fulfilled" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202910-f3e19580-348a-11ea-8a00-49c005f3cdd3.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 2&lt;/em&gt;: ⚡️ One or more of the passed-in Promise(s) rejects&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202911-f3e19580-348a-11ea-99ff-850ced214ddb.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️Promise.all - One or more of the passed-in Promise(s) rejects" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202911-f3e19580-348a-11ea-99ff-850ced214ddb.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 3&lt;/em&gt;: ⚡️ All passed-in Promises get rejected&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202912-f47a2c00-348a-11ea-9ff2-ad6d86514c8c.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️Promise.all - All passed-in Promises get rejected" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202912-f47a2c00-348a-11ea-9ff2-ad6d86514c8c.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 4&lt;/em&gt;:  Passing an Empty iterable&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202913-f47a2c00-348a-11ea-9642-684ffb5b771e.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.all - Passing an Empty iterable" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72202913-f47a2c00-348a-11ea-9642-684ffb5b771e.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;Promise.allSettled&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Scenario 1&lt;/em&gt;: All passed-in Promises get fulfilled&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213854-0c4dc080-351c-11ea-9646-c6917ae7df2d.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.allSettled - All passed-in Promises get fulfilled" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213854-0c4dc080-351c-11ea-9646-c6917ae7df2d.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 2&lt;/em&gt;:  One or more of the passed-in Promise(s) rejects&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213855-0ce65700-351c-11ea-947d-b0be63329f3d.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.allSettled - One or more of the passed-in Promise(s) rejects" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213855-0ce65700-351c-11ea-947d-b0be63329f3d.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 3&lt;/em&gt;:  All passed-in Promises get rejected&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213856-0d7eed80-351c-11ea-9961-06d869c9655e.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.allSettled - All passed-in Promises get rejected" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213856-0d7eed80-351c-11ea-9961-06d869c9655e.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 4&lt;/em&gt;:  Passing an Empty iterable&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213857-0d7eed80-351c-11ea-8766-6425dfa4f3e4.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.allSettled - Passing an Empty iterable" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72213857-0d7eed80-351c-11ea-8766-6425dfa4f3e4.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;Promise.race&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Scenario 1&lt;/em&gt;: ⚡️ All passed-in Promises get fulfilled&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214065-79635500-3520-11ea-937e-5d89d2ce1aa5.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️Promise.race - All passed-in Promises get fulfilled" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214065-79635500-3520-11ea-937e-5d89d2ce1aa5.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 2&lt;/em&gt;: ⚡️ One or more of the passed-in Promise(s) rejects&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214066-79635500-3520-11ea-9544-949800bb450f.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️Promise.race - One or more of the passed-in Promise(s) rejects" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214066-79635500-3520-11ea-9544-949800bb450f.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 3&lt;/em&gt;: ⚡️ All passed-in Promises get rejected&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214067-79635500-3520-11ea-8737-e6c3198dc2ad.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️Promise.race - All passed-in Promises get rejected" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214067-79635500-3520-11ea-8737-e6c3198dc2ad.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 4&lt;/em&gt;:  Passing an Empty iterable&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214068-79635500-3520-11ea-999b-6cbfdc073014.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.race - Passing an Empty iterable" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214068-79635500-3520-11ea-999b-6cbfdc073014.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;code&gt;Promise.any&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;⚠️ Warning&lt;/code&gt; - Promise.any() method is experimental and not fully supported by all browsers. It is currently in the TC39 Candidate stage (Stage 3).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Scenario 1&lt;/em&gt;: ⚡️ All passed-in Promises get fulfilled&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214139-6487c100-3522-11ea-9cc7-137b7f700c0f.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️ Promise.any - All passed-in Promises get fulfilled" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214139-6487c100-3522-11ea-9cc7-137b7f700c0f.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 2&lt;/em&gt;: ⚡️ One or more of the passed-in Promise(s) rejects&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214140-6487c100-3522-11ea-9527-609bcc583889.gif" class="article-body-image-wrapper"&gt;&lt;img alt="⚡️ Promise.any - One or more of the passed-in Promise(s) rejects" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214140-6487c100-3522-11ea-9527-609bcc583889.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 3&lt;/em&gt;:  All passed-in Promises get rejected&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214141-65205780-3522-11ea-96e1-9a8697316fb8.gif" class="article-body-image-wrapper"&gt;&lt;img alt=" Promise.any - All passed-in Promises get rejected" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214141-65205780-3522-11ea-96e1-9a8697316fb8.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Scenario 4&lt;/em&gt;:  Passing an Empty iterable&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214142-65205780-3522-11ea-83e7-fbd3bb4e1c18.gif" class="article-body-image-wrapper"&gt;&lt;img alt="Promise.any - Passing an Empty iterable" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F19341550%2F72214142-65205780-3522-11ea-83e7-fbd3bb4e1c18.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And hey, I love staying in touch with the curious folks and &lt;em&gt;learning&lt;/em&gt; from them as well! ❤️ So, Please feel free to reach out if you have any questions or interesting thoughts 🙋‍♀️🙋‍♂️Don't forget to share this post if you found it useful 🚀&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://twitter.com/HemSays" rel="noopener noreferrer"&gt;🐥Twitter&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://www.linkedin.com/in/hems23/" rel="noopener noreferrer"&gt;💼LinkedIn&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;Repo Link : &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/hemchander23" rel="noopener noreferrer"&gt;
        hemchander23
      &lt;/a&gt; / &lt;a href="https://github.com/hemchander23/javascript_in_gifs" rel="noopener noreferrer"&gt;
        javascript_in_gifs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Javascript concepts and features visualised in the form of GIFS. I use it for my own reference. Glad if it was useful for you !
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Javascript in GIFs 🎉&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Do you find the documentation hard to understand ? Worry no more, the GIFs got you covered!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contents&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/hemchander23/javascript_in_gifspromise_api" rel="noopener noreferrer"&gt;Promise API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hemchander23/javascript_in_gifsnullish_coalescing" rel="noopener noreferrer"&gt;Nullish Coalescing&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Feel free to contribute ❤️&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/hemchander23/javascript_in_gifs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>javascript</category>
      <category>design</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>🥋Few tips to make developers not wrestle with your APIs</title>
      <dc:creator>Hem</dc:creator>
      <pubDate>Wed, 01 Jan 2020 18:23:51 +0000</pubDate>
      <link>https://dev.to/hem/few-tips-to-make-developers-not-wrestle-with-your-apis-4bc8</link>
      <guid>https://dev.to/hem/few-tips-to-make-developers-not-wrestle-with-your-apis-4bc8</guid>
      <description>&lt;p&gt;Often, APIs are the first point of contact for developers and significantly impact Developer Experience(DX). Developer-friendly APIs will improve adoption, retention and might also instill a good word-of-mouth awareness among the developer community. At the end of the day, an API has to provide an interface using which products/ applications can talk to each other. Adding a few more traits to this baseline definition does not only deliver a good interface but also provides a great developer experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  1️⃣ Documentation
&lt;/h1&gt;

&lt;p&gt;This is the first and foremost factor for successful APIs. Neatly documented endpoints with clear descriptions enable developers to understand and leverage them easily. Interactive API documentation stands out and is beneficial when you have a lot of APIs to offer. At the minimal, the capability to try it out in POSTMAN or other REST clients could save time for the developer and can make things easier. &lt;/p&gt;

&lt;p&gt;Good documentation also covers things that the developers might miss hurriedly (most probably during their 1st pass) for example - rate limit policies, paginations, authentication, etc. It should drive developers towards the &lt;a href="https://blog.codinghorror.com/falling-into-the-pit-of-success/"&gt;pit of success&lt;/a&gt; by default&lt;/p&gt;

&lt;h1&gt;
  
  
  2️⃣ Graceful changes, deprecations
&lt;/h1&gt;

&lt;p&gt;Change is inevitable. It is good for progress. However, it becomes our duty to convey changes to developers as and when they occur. Most importantly, being mindful of users who have already consumed the API and introducing changes gracefully can alleviate major issues.&lt;/p&gt;

&lt;p&gt;Communicating it via developer portals, changelogs, forums, etc. will significantly reduce friction.&lt;/p&gt;

&lt;h1&gt;
  
  
  3️⃣ Proper Error response/Status codes
&lt;/h1&gt;

&lt;p&gt;I wish to live in a world where there were more &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418"&gt;418&lt;/a&gt;-like status codes. However, it is always recommended to stick to meaningful error codes that convey upfront information to the user without them having to sherlock it. &lt;/p&gt;

&lt;p&gt;Developers will be able to connect the dots and solve the issue at a much lesser time if the error code makes sense. The advantage of such status codes is that it implicitly delegates problem-solving to the developer and makes them informed in that situation. Otherwise, this might end up as support tickets and forum queries.&lt;/p&gt;

&lt;h1&gt;
  
  
  4️⃣ Avoid too chatty/chunky
&lt;/h1&gt;

&lt;p&gt;Chatty APIs will lead to making multiple network calls to perform a single task. This ideally should be one single API call. On the other hand, chunky APIs end up providing too much information in one single call. It is recommended to avoid the extremes&lt;/p&gt;

&lt;p&gt;These are a few tips that I follow to ensure that developers don't wrestle with the APIs. I would like to hear your thoughts as well in the comments section! 😀❤️ &lt;/p&gt;

</description>
      <category>devrel</category>
      <category>api</category>
      <category>rest</category>
      <category>documentation</category>
    </item>
  </channel>
</rss>
