<?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: Aaron Goldsmith</title>
    <description>The latest articles on DEV Community by Aaron Goldsmith (@aarongoldsmith1).</description>
    <link>https://dev.to/aarongoldsmith1</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%2F555253%2Fb211f177-d42e-44ce-aff3-f6f961afe9c4.jpg</url>
      <title>DEV Community: Aaron Goldsmith</title>
      <link>https://dev.to/aarongoldsmith1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aarongoldsmith1"/>
    <language>en</language>
    <item>
      <title>Twitch.tv API - Get live stream data from paginated results</title>
      <dc:creator>Aaron Goldsmith</dc:creator>
      <pubDate>Mon, 29 Mar 2021 04:23:02 +0000</pubDate>
      <link>https://dev.to/aarongoldsmith1/twitch-tv-api-get-live-stream-data-from-paginated-results-4ama</link>
      <guid>https://dev.to/aarongoldsmith1/twitch-tv-api-get-live-stream-data-from-paginated-results-4ama</guid>
      <description>&lt;p&gt;Recently, I wanted to work with the Twitch API to try to recreate the website &lt;a href="https://twitchroulette.net/" rel="noopener noreferrer"&gt;twitchroulette.net&lt;/a&gt;, where you would be able to view a completely random live stream from all of the streams currently happening on the site.  According to analytics from &lt;a href="https://twitchtracker.com/statistics/channels" rel="noopener noreferrer"&gt;twitchtracker.com&lt;/a&gt;, there are currently an average of over 100,000 Twitch live streams at any given time.&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%2Fuploads%2Farticles%2Fnhdkx120q1c15urtyosh.PNG" 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%2Fuploads%2Farticles%2Fnhdkx120q1c15urtyosh.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I went through the &lt;a href="https://dev.twitch.tv/docs/api/reference#get-streams" rel="noopener noreferrer"&gt;Twitch API documentation&lt;/a&gt;, I discovered that for the endpoint &lt;code&gt;https://api.twitch.tv/helix/streams&lt;/code&gt; to get live streams, Twitch limits the response to a maximum of 100 streams per API call.  However, the response includes a &lt;code&gt;pagination&lt;/code&gt; field which contains a &lt;code&gt;cursor&lt;/code&gt; value (a string) which is used in a subsequent requests to specify the starting point of the next set of results.  &lt;/p&gt;

&lt;p&gt;The response body for the GET request at &lt;code&gt;https://api.twitch.tv/helix/streams?first=100&lt;/code&gt; would include the top 100 most active live streams, and the data looks 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;{
  "data": [
    {
      "id": "41375541868",
      "user_id": "459331509",
      "user_login": "auronplay",
      "user_name": "auronplay",
      "game_id": "494131",
      "game_name": "Little Nightmares",
      "type": "live",
      "title": "hablamos y le damos a Little Nightmares 1",
      "viewer_count": 78365,
      "started_at": "2021-03-10T15:04:21Z",
      "language": "es",
      "thumbnail_url": "https://static-cdn.jtvnw.net/previews-ttv/live_user_auronplay-{width}x{height}.jpg",
      "tag_ids": [
        "d4bb9c58-2141-4881-bcdc-3fe0505457d1"
      ]
    },
    ...
  ],
  "pagination": {
    "cursor": "eyJiIjp7IkN1cnNvciI6ImV5SnpJam8zT0RNMk5TNDBORFF4TlRjMU1UY3hOU3dpWkNJNlptRnNjMlVzSW5RaU9uUnlkV1Y5In0sImEiOnsiQ3Vyc29yIjoiZXlKeklqb3hOVGs0TkM0MU56RXhNekExTVRZNU1ESXNJbVFpT21aaGJITmxMQ0owSWpwMGNuVmxmUT09In19"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you wanted to retrieve the next 100 most active live streams, the subsequent API request URL would need to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.twitch.tv/helix/streams?first=100&amp;amp;after=eyJiIjp7IkN1cnNvciI6ImV5SnpJam8zT0RNMk5TNDBORFF4TlRjMU1UY3hOU3dpWkNJNlptRnNjMlVzSW5RaU9uUnlkV1Y5In0sImEiOnsiQ3Vyc29yIjoiZXlKeklqb3hOVGs0TkM0MU56RXhNekExTVRZNU1ESXNJbVFpT21aaGJITmxMQ0owSWpwMGNuVmxmUT09In19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 This includes as its &lt;code&gt;after&lt;/code&gt; value the cursor value returned in the prior response.&lt;/p&gt;

&lt;p&gt;It's not possible to sort the responses by least active, so in order to get results with streams with very few or no viewers, you would need results for the more active streams first.&lt;/p&gt;

&lt;p&gt;It is also important to note that the Twitch API is rate-limited to 800 requests per minute, so the maximum number of livestreams we could retrieve in that time is 80,000, which is substantially lower than the current weekly average.  It's therefore plausible that trying to get a truly complete list of results for live streams would run the risk of causing a HTTP 429 error (too many requests).&lt;/p&gt;

&lt;p&gt;In order to try to retrieve as many live streams as possible, while keeping in mind the constraints of the rate-limit and a potentially impatient user, I approached this problem using recursion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getAllStreams (cursor, data = [], counter = 15) {
  while (counter !== 0) {
    const request = new Request('https://api.twitch.tv/helix/streams?first=100' + (cursor ? '&amp;amp;after=' + cursor : ''), { 
      method: 'GET' ,
      headers: {
        'Client-ID': clientId,
        'Authorization': `Bearer ${access_token}`,
        'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
        }
      });

    return fetch(request).then((response) =&amp;gt; response.json()).then((responseJson) =&amp;gt; { 
      if (counter === 1) return data;
      data.push(...responseJson.data);
      return getAllStreams(responseJson.pagination.cursor, data, --counter);
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I found that each request took about half a second to complete, so that meant I also needed to limit the number of requests made in order to keep the user engaged, and I specify that limit as a default argument &lt;code&gt;counter&lt;/code&gt;.  While 1500 streams might not seem like a big number, it does make it possible to recreate the experience of viewing a single random stream.&lt;/p&gt;

&lt;p&gt;I would appreciate any suggestions or critiques of my approach, as this was the first time I've worked with and tried to 'crawl' a paginated API.  I just wanted to share the way I went about using this endpoint in order to try to help other developers who attempt to do the same.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Logical Assignment Operators</title>
      <dc:creator>Aaron Goldsmith</dc:creator>
      <pubDate>Sat, 09 Jan 2021 05:58:54 +0000</pubDate>
      <link>https://dev.to/aarongoldsmith1/logical-assignment-operators-1g62</link>
      <guid>https://dev.to/aarongoldsmith1/logical-assignment-operators-1g62</guid>
      <description>&lt;p&gt;Javascript (ES2021) now supports the ability to combine logical operations and assignment with the new operators &lt;code&gt;&amp;amp;&amp;amp;=&lt;/code&gt;, &lt;code&gt;||=&lt;/code&gt;, and &lt;code&gt;??=&lt;/code&gt;.  Previously, compound assignment operators were only possible with mathematical and bitwise operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logical AND assignment &lt;code&gt;&amp;amp;&amp;amp;=&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The logical AND assignment &lt;code&gt;x &amp;amp;&amp;amp;= y&lt;/code&gt; operator performs assignment only if &lt;code&gt;x&lt;/code&gt; is truthy.  For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let a = 1;
let b = 0;

a &amp;amp;&amp;amp;= 2;
console.log(a); // output: 2

b &amp;amp;&amp;amp;= 2;
console.log(b); // output: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Short-circuit evaluation
&lt;/h4&gt;

&lt;p&gt;If the left-hand expression is falsy, it is short-circuit evaluated and the right-hand expression is not evaluated, so the value of &lt;code&gt;b&lt;/code&gt; is not reassigned because 0 is falsy.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;a &amp;amp;&amp;amp;= 2&lt;/code&gt; is equivalent to &lt;code&gt;a &amp;amp;&amp;amp; (a = 2)&lt;/code&gt;, and the value of &lt;code&gt;a&lt;/code&gt; is reassigned because it was originally truthy.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Logical OR assignment &lt;code&gt;||=&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The logical OR assignment &lt;code&gt;x ||= y&lt;/code&gt; operator only assigns if &lt;code&gt;x&lt;/code&gt; is falsy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a = 50;
const b = '';

a ||= 10;
console.log(a);  // output: 50

b ||= 'string is empty.';
console.log(b); // output: "string is empty."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Short-circuit evaluation
&lt;/h4&gt;

&lt;p&gt;From the above example, &lt;code&gt;a ||= 10&lt;/code&gt; is equivalent to &lt;code&gt;a || (a = 10)&lt;/code&gt;, but because the value of &lt;code&gt;a&lt;/code&gt; is truthy, it is short-circuit evaluated and the right-hand assignment is not evaluated.&lt;/p&gt;

&lt;p&gt;If you are checking against a falsy value such as an empty string or 0, &lt;code&gt;||=&lt;/code&gt; must be used, otherwise the logical nullish assignment operator &lt;code&gt;??=&lt;/code&gt; should be used to check for &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logical nullish assignment &lt;code&gt;??=&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The logical nullish assignment &lt;code&gt;x ??= y&lt;/code&gt; operator only assigns if &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const a = { limt: 50 };

a.limit ??= 10;
console.log(a.limit); // output: 50

a.speed ??= 25;
console.log(a.speed); // output: 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Short-circuit evaluation
&lt;/h4&gt;

&lt;p&gt;A logical nullish assignment expression is short-circuit evaluated to the left-hand side expression if the left-hand side is neither &lt;code&gt;null&lt;/code&gt; nor &lt;code&gt;undefined&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;In the above example, the reassignment of &lt;code&gt;a.limit&lt;/code&gt; is not performed because its value is defined as 50, which is not &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;a.speed&lt;/code&gt; would initially evaluate to &lt;code&gt;undefined&lt;/code&gt;, so the right-hand expression is evaluated, which is equivalent to &lt;code&gt;a.speed = 25&lt;/code&gt;, and now &lt;code&gt;a = {limit: 50, speed: 25}&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Nullish Coalescing Operator</title>
      <dc:creator>Aaron Goldsmith</dc:creator>
      <pubDate>Fri, 08 Jan 2021 04:33:46 +0000</pubDate>
      <link>https://dev.to/aarongoldsmith1/nullish-coalescing-operator-pi0</link>
      <guid>https://dev.to/aarongoldsmith1/nullish-coalescing-operator-pi0</guid>
      <description>&lt;p&gt;The nullish coalescing operator &lt;code&gt;??&lt;/code&gt; is a logical operator that returns its right-hand side operand when its left-hand side operand is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;, and otherwise returns its left-hand side operand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const nullValue = null;

const val1 = nullValue ?? "default";

console.log(val1); // "default"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is similar to the traditional 'or' logical operator &lt;code&gt;||&lt;/code&gt;, but the difference is that &lt;code&gt;||&lt;/code&gt; will return the right-hand side operand with any falsy value, such as an empty string, 0 or &lt;code&gt;NaN&lt;/code&gt;, not only &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const val = null ?? 'default';
console.log(val);
// logs "default"

const val2 = 0 ?? 88;
console.log(val2);
// logs 0 because it is falsy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is possible to use the nullish coalescing operator in combination with the traditional AND &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; and OR &lt;code&gt;||&lt;/code&gt; operators, but the statements that include those logical operators must be enclosed in parentheses, or it will raise a syntax error.  For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;null || undefined ?? "value"; // SyntaxError
false || undefined ?? "value"; // SyntaxError

(null || undefined) ?? "value"; // returns "value"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A common pattern is to use the nullish coalescing operator with the optional chaining operator &lt;code&gt;?.&lt;/code&gt;, which is useful to access a property of an object which may be &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const obj = { prop1: "hello" };

console.log(obj.prop1?.toUpperCase() ?? "error"); // "HELLO"
console.log(obj.prop2?.toUpperCase() ?? "error"); // "error"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Optional Chaining Operator</title>
      <dc:creator>Aaron Goldsmith</dc:creator>
      <pubDate>Thu, 07 Jan 2021 07:49:29 +0000</pubDate>
      <link>https://dev.to/aarongoldsmith1/optional-chaining-operator-4i9l</link>
      <guid>https://dev.to/aarongoldsmith1/optional-chaining-operator-4i9l</guid>
      <description>&lt;p&gt;The optional chaining operator &lt;code&gt;?.&lt;/code&gt; is a new Javascript language feature introduced in ES2020.  It provides a way to access nested object properties without having to expressly validate that each reference in the chain is valid. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;?.&lt;/code&gt; operator functions similarly to the &lt;code&gt;.&lt;/code&gt; chaining operator, except that instead of causing an error if a reference is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;, the expression returns a value of &lt;code&gt;undefined&lt;/code&gt;.  When used with function calls, it returns &lt;code&gt;undefined&lt;/code&gt; if the given function does not exist.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const obj = {
  prop1: {
    prop2: {
      prop3: "value"
    }
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you attempted access a property in the above object that didn't exist: &lt;code&gt;obj.prop2.prop3&lt;/code&gt; that would throw the following error:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Uncaught TypeError: Cannot read property 'prop3' of undefined&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Typically, you could try to handle the case of potentially missing property by combining logical operators and a ternary expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myProp3 = obj.prop2 &amp;amp;&amp;amp; obj.prop2.prop3 ? obj.prop2.prop3 : undefined;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This verbose syntax can be written instead using the optional chaining operator which will automatically assign the value of &lt;code&gt;myProp3&lt;/code&gt; to &lt;code&gt;undefined&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myProp3 = obj.prop2?.prop3; //undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For dealing with even more deeply nested objects, the optional chaining operator can be used multiple times in the same statement to safely accommodate the accessing of properties: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;let temp = obj.first?.second?.third?.value;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It can also be used with function calls to make sure a function exists, and if it doesn't will return &lt;code&gt;undefined&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let data = obj.someMethod?.(someArgument);  //undefined&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It can also be used with arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arr = [5,6,7,8];

arr?.[10] // undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the Map data structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let myMap = new Map();
myMap.set("foo", {name: "baz", desc: "inga"});

let nameBar = myMap.get("bar")?.name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, with the nullish coalescing operator &lt;code&gt;??&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myCar = {
  make: "Ford",
  details: { year: 1982 }
};
const customerCar = myCar?.make ?? "Unknown Car";
console.log(customerCity); // Unknown Car
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
