Practical ways to write better JavaScript

catalogue

 

Use type script

Type scripts enforce type safety

Type descriptions make it possible to refactor larger applications

Type scripts make team architecture communication easier

Use modern features

Synchronization and waiting

Jean and conster

Arrow = = function

Propagation operator

Template font (template string)

Object construction

Always assume that your system has been distributed

Modify your code and enforce styles

Test your code

Test driver – EVA

Spies and stubs Sinon

MOX Nock

Network automation - uranium

An endless journey

Use type script

The first thing to improve JS is not to write JS. For not started ,TypeScript (TS) Is the "compiled" superset of JS (any TS running in JS). TS adds a comprehensive optional typing system based on Vanilla JS experience. For a long time, the TS support of the whole ecosystem is inconsistent, so that I am reluctant to recommend it. Fortunately, those days are long gone, and most frameworks support ts out of the box. Now that we're all on the same page about what TS is, let's talk about why you want to use it.


Type scripts enforce type safety

Type safety describes the process by which the compiler verifies that all types are used legally throughout the code. In other words, if you create a function that requires numbers: foo

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">foo</span>(someNum: number): <span style="color:var(--highlight-literal)">number</span> {
  <span style="color:var(--highlight-keyword)">return</span> someNum + <span style="color:var(--highlight-namespace)">5</span>;
}</code></span>

This function applies only digital calls: foo

 

<span style="color:#3c4146"><em>good</em></span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-symbol)">console</span>.log(foo(<span style="color:var(--highlight-namespace)">2</span>)); // prints <span style="color:var(--highlight-variable)">"7"</span></code></span>
<span style="color:#3c4146"><em>no good</em></span>
<span style="color:var(--highlight-color)"><code>console.<span style="color:var(--highlight-literal)">log</span>(foo(<span style="color:var(--highlight-variable)">"two"</span>)); <span style="color:var(--highlight-comment)">// invalid TS code</span></code></span>

In addition to adding types to code, type safe execution has no disadvantages. On the other hand, the benefits are too great to be ignored. Type safety provides an additional level of protection against common errors / errors, which is a blessing for lawless languages like JS.

 

 

Type descriptions make it possible to refactor larger applications

Refactoring large JS applications can be a real nightmare. Most of the pain of refactoring JS is that it does not enforce function signatures. This means that JS functions will never be really abused. For example, if I have a function for 1000 different services: myAPI

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">myAPI</span>(someNum, someString) {
  <span style="color:var(--highlight-keyword)">if</span> (someNum > <span style="color:var(--highlight-namespace)">0</span>) {
    leakCredentials();
  } <span style="color:var(--highlight-keyword)">else</span> {
    <span style="color:var(--highlight-literal)">console</span>.log(someString);
  }
}</code></span>

I changed the call signature:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">myAPI</span>(someString, someNum) {
  <span style="color:var(--highlight-keyword)">if</span> (someNum > <span style="color:var(--highlight-namespace)">0</span>) {
    leakCredentials();
  } <span style="color:var(--highlight-keyword)">else</span> {
    <span style="color:var(--highlight-literal)">console</span>.log(someString);
  }
}</code></span>

I have to be 100% sure that everywhere I use this feature (thousands of locations), I have updated my usage correctly. If I even miss one, my credentials may leak. The following is the same scheme for TS:

<span style="color:#3c4146"><em>before</em></span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">myAPITS</span>(someNum: number, someString: <span style="color:var(--highlight-keyword)">string</span>) { ... }</code></span>
<span style="color:#3c4146"><em>after</em></span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">myAPITS</span>(someString: <span style="color:var(--highlight-keyword)">string</span>, someNum: number) { ... }</code></span>

As you can see, this function has undergone the same changes as its JavaScript counterpart. However, this code will not result in valid JavaScript, but will invalidate the "type script" because it uses thousands of locations that now provide the wrong type. Because of the type security we discussed earlier, these 1000 cases will prevent assembly and your credentials will not be compromised (which is always good). myAPITS


Type scripts make team architecture communication easier

When the TS is set correctly, it will be difficult to write code without defining the interface and class first. This provides a way to share concise, communicative architectural recommendations. Before ts, there were other solutions to this problem, but none of them were solved locally without making you do extra work. For example, if I want to propose a new type for my backend, I can use ts to send the following types to my teammates. Request

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">interface</span> <span style="color:var(--highlight-keyword)">BasicRequest</span> {
  <span style="color:var(--highlight-symbol)">body</span>: Buffer;
  <span style="color:var(--highlight-symbol)">headers</span>: { [header: string]: string | string[] | undefined; };
  <span style="color:var(--highlight-keyword)">secret</span>: <span style="color:var(--highlight-keyword)">Shhh</span>;
}</code></span>

I've had to write code, but now I can share my incremental progress and get feedback without investing more time. I don't know if TS itself is more error prone than JS. I firmly believe that forcing developers to define interfaces and API s will first lead to better code.

In general, TS has developed into a mature and more predictable alternative to vanilla JS. Developers certainly still need to be satisfied with vanilla JS, but most of the new projects I start these days are ts from the beginning.
 

 


Use modern features

JavaScript is one of the most popular (if not the most) programming languages in the world. You might think that most of the languages used by hundreds of millions of people more than 20 years ago will now be understood, but the opposite is true. I know that a lot of changes have been made to the technical experience of mascript. As a person who has only started writing JS in the past two years, my advantage is that I have no prejudice or expectation. This leads to more pragmatic choices about which features of the language to use and which to avoid.


Synchronization and waiting

For a long time, asynchronous and event driven callback has been an inevitable part of JS development:

<span style="color:#3c4146"><em>traditional callback</em></span>
<span style="color:var(--highlight-color)"><code>makeHttpRequest(<span style="color:var(--highlight-variable)">'google.com'</span>, <span style="color:var(--highlight-keyword)">function</span> (err, result) {
  <span style="color:var(--highlight-keyword)">if</span> (err) {
    <span style="color:var(--highlight-literal)">console</span>.log(<span style="color:var(--highlight-variable)">'Oh boy, an error'</span>);
  } <span style="color:var(--highlight-keyword)">else</span> {
    <span style="color:var(--highlight-literal)">console</span>.log(result);
  }
});</code></span>

I won't take the time to explain why there are problems on it( But I used to ) . In order to solve the callback problem, a new concept commitment is added to JS. The promise allows you to write asynchronous logic while avoiding the nesting problems that previously plagued callback based code.

<span style="color:#3c4146"><em>Promises</em></span>
<span style="color:var(--highlight-color)"><code>makeHttpRequest(<span style="color:var(--highlight-variable)">'google.com'</span>).then(<span style="color:var(--highlight-keyword)">function</span> (result) {
  <span style="color:var(--highlight-literal)">console</span>.log(result);
}).catch(<span style="color:var(--highlight-keyword)">function</span> (err) {
  <span style="color:var(--highlight-literal)">console</span>.log(<span style="color:var(--highlight-variable)">'Oh boy, an error'</span>);
});</code></span>

The biggest advantage of commitment over callback is readability and chainability.

Although the promise is great, they still leave something to improve. For many people, the commitment experience is still reminiscent of callback. Specifically, developers require alternative commitment patterns. In order to solve this problem, the ECMAScript committee decided to add a new method of using commitment and: asyncawait

<span style="color:#3c4146">
<em><code>async</code> and <code>await</code></em>
</span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">try</span> {
  <span style="color:var(--highlight-keyword)">const</span> result = <span style="color:var(--highlight-keyword)">await</span> makeHttpRequest(<span style="color:var(--highlight-variable)">'google.com'</span>);
  <span style="color:var(--highlight-literal)">console</span>.log(result);
} <span style="color:var(--highlight-keyword)">catch</span> (err) {
  <span style="color:var(--highlight-literal)">console</span>.log(<span style="color:var(--highlight-variable)">'Oh boy, an error'</span>);
}</code></span>

A warning is that any you have to be announced: awaitasync

<span style="color:#3c4146"><em>required definition of makeHttpRequest in prev example</em></span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">async</span> <span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">makeHttpRequest</span>(url) {
  <span style="color:var(--highlight-comment)">// ...</span>
}</code></span>

It can also be directly promised, because a function is really just a fancy promise package. This also means that the code and commitment code are functionally equivalent. Therefore, please feel free to use it without feeling guilty. awaitasyncasync/awaitasync/await


Jean and conster
 

Most of the time JS existed, there was only one variable range qualifier:. There are some very unique / interesting rules about how it deals with scope. Scope behavior is inconsistent and chaotic, and leads to unexpected behavior and therefore errors throughout the life of JS. But as of ES6, there is an alternative: and. There's almost no need to reuse it, so don't use it again. Any logic used can be converted to equivalent and code based. varvarvarvarconstletvarvarconstlet

 

As for when to use and, I always start by announcing everything. Is more stringent and "immediate", which usually leads to better code. Without a ton of "real scene", the use is necessary. I will say 1 / 20 variable, which I announce with. The rest are. constletconstconstletletconst

 

I say "fixed" because it works differently from C/C + +. The meaning of JavaScript runtime is that the reference to this variable will never change. This does not mean that the content stored in the reference will never change. For primitive types (numbers, Booleans, etc.), it does convert to immutability (because it is a single memory address). But for all objects (classes, arrays, dictation), there is no guarantee of immutability. constconstconstconstconstconst



Arrow = = function
 

The arrow function is declared in JS Anonymous function A concise approach. Anonymous functions describe functions that are not explicitly named. Typically, anonymous functions are passed as callbacks or event hooks.

<span style="color:#3c4146">
<em>vanilla anonymous function</em>
</span>
<span style="color:var(--highlight-color)"><code>someMethod(<span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-keyword)">function</span> () { <span style="color:var(--highlight-comment)">// has no name</span>
  <span style="color:var(--highlight-literal)">console</span>.log(<span style="color:var(--highlight-variable)">'called'</span>);
});</code></span>

In most cases, this style has no "mistakes". Vanilla anonymity is "interesting" in terms of scope, which can lead to many unexpected errors. Due to the arrow function, we don't have to worry about this problem anymore. The following is the same code implemented by the arrow function:

<span style="color:#3c4146"><em>anonymous arrow function</em></span>
<span style="color:var(--highlight-color)"><code>someMethod(<span style="color:var(--highlight-namespace)">1</span>, () => { <span style="color:var(--highlight-variable)">//</span> has <span style="color:var(--highlight-literal)">no</span> name
  <span style="color:var(--highlight-literal)">console</span>.log(<span style="color:var(--highlight-variable)">'called'</span>);
});</code></span>

In addition to being more concise, the arrow function also has more practical defining behavior. The arrow function inherits from the defined scope. this

In some cases, the arrow function can be more concise:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">added</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">0</span>, <span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>, <span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>]<span style="color:var(--highlight-variable)">.map((item)</span> <span style="color:var(--highlight-variable)">=></span> <span style="color:var(--highlight-variable)">item</span> <span style="color:var(--highlight-variable)">+</span> <span style="color:var(--highlight-namespace)">1</span><span style="color:var(--highlight-variable)">);</span>
<span style="color:var(--highlight-variable)">console.log(added)</span> <span style="color:var(--highlight-variable)">//</span> <span style="color:var(--highlight-variable)">prints</span> <span style="color:var(--highlight-variable)">"[1, 2, 3, 4, 5]"</span></code></span>

The arrow function on a single line includes implied statements. Brackets or semi colons with single line arrow function are not required. return

I want to make it clear. This is not the case. Vanilla anonymity (especially class methods) still has effective use cases. In other words, I found that if you always default to the arrow function, you will end up doing a lot less debugging than the default function. var

<span style="color:#3c4146"><a data-cke-saved-href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">As usual, the Mozilla docs are the best resource</a></span>



Propagation operator
 

It is a very common scene to extract the key / value pair of one object and add it as a child of another object. Historically, there are several ways to do this, but all of them are quite cumbersome:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">const</span> obj1 = { <span style="color:var(--highlight-attribute)">dog</span>: <span style="color:var(--highlight-variable)">'woof'</span> };
<span style="color:var(--highlight-keyword)">const</span> obj2 = { <span style="color:var(--highlight-attribute)">cat</span>: <span style="color:var(--highlight-variable)">'meow'</span> };
<span style="color:var(--highlight-keyword)">const</span> merged = <span style="color:var(--highlight-literal)">Object</span>.assign({}, obj1, obj2);
<span style="color:var(--highlight-literal)">console</span>.log(merged) <span style="color:var(--highlight-comment)">// prints { dog: 'woof', cat: 'meow' }</span></code></span>

This pattern is very common, so the above method quickly becomes boring. Because of the propagation operator, it is no longer needed:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">const</span> obj1 = { <span style="color:var(--highlight-attribute)">dog</span>: <span style="color:var(--highlight-variable)">'woof'</span> };
<span style="color:var(--highlight-keyword)">const</span> obj2 = { <span style="color:var(--highlight-attribute)">cat</span>: <span style="color:var(--highlight-variable)">'meow'</span> };
<span style="color:var(--highlight-literal)">console</span>.log({ ...obj1, ...obj2 }); <span style="color:var(--highlight-comment)">// prints { dog: 'woof', cat: 'meow' }</span></code></span>

Best of all, it also works seamlessly with the array:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">arr1</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>]<span style="color:var(--highlight-variable)">;</span>
<span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">arr2</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>]<span style="color:var(--highlight-variable)">;</span>
<span style="color:var(--highlight-variable)">console.log([</span> <span style="color:var(--highlight-variable)">...arr1,</span> <span style="color:var(--highlight-variable)">...arr2</span> <span style="color:var(--highlight-variable)">]);</span> <span style="color:var(--highlight-variable)">//</span> <span style="color:var(--highlight-variable)">prints</span> [<span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>, <span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>]</code></span>

This may not be the most important JS feature recently, but it is one of my favorite features.



Template font (template string)

String is one of the most common programming constructs. That's why it's so embarrassing that local announcement strings still lack support in many languages. For a long time, JS was in the "bad string" family. However, the addition of templates literally puts JS into its own category. Template literal text is native and easy to solve the two biggest problems and writing strings: adding dynamic content and writing strings, bridging multiple lines:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">const</span> name = <span style="color:var(--highlight-variable)">'Ryland'</span>;
<span style="color:var(--highlight-keyword)">const</span> helloString =
<span style="color:var(--highlight-variable)">`Hello
 <span style="color:var(--highlight-color)">${name}</span>`</span>;</code></span>

I think the code is self-evident. What an amazing realization.



Object construction
 

Object corruption is a way to extract values from data collection (objects, arrays, etc.) without repeating or explicitly accessing their keys on the data:

<span style="color:#3c4146"><em>old way</em></span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">animalParty</span>(dogSound, catSound) {}

<span style="color:var(--highlight-keyword)">const</span> myDict = {
  <span style="color:var(--highlight-attribute)">dog</span>: <span style="color:var(--highlight-variable)">'woof'</span>,
  <span style="color:var(--highlight-attribute)">cat</span>: <span style="color:var(--highlight-variable)">'meow'</span>,
};

animalParty(myDict.dog, myDict.cat);</code></span>

destruction

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">animalParty</span>(dogSound, catSound) {}

<span style="color:var(--highlight-keyword)">const</span> myDict = {
  <span style="color:var(--highlight-attribute)">dog</span>: <span style="color:var(--highlight-variable)">'woof'</span>,
  <span style="color:var(--highlight-attribute)">cat</span>: <span style="color:var(--highlight-variable)">'meow'</span>,
};

<span style="color:var(--highlight-keyword)">const</span> { dog, cat } = myDict;
animalParty(dog, cat);</code></span>

But wait a minute, there's more. You can also define destruction in the feature signature:

<span style="color:#3c4146"><em>destructuring 2</em></span>
<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">function</span> <span style="color:var(--highlight-literal)">animalParty</span>({ dog, cat }) {}

<span style="color:var(--highlight-keyword)">const</span> myDict = {
  <span style="color:var(--highlight-attribute)">dog</span>: <span style="color:var(--highlight-variable)">'woof'</span>,
  <span style="color:var(--highlight-attribute)">cat</span>: <span style="color:var(--highlight-variable)">'meow'</span>,
};

animalParty(myDict);</code></span>

It also applies to arrays:

<span style="color:#3c4146"><em>destructuring 3</em></span>
<span style="color:var(--highlight-color)"><code>[<span style="color:var(--highlight-variable)">a</span>, <span style="color:var(--highlight-variable)">b</span>] <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">10</span>, <span style="color:var(--highlight-namespace)">20</span>]<span style="color:var(--highlight-variable)">;</span>

<span style="color:var(--highlight-variable)">console.log(a);</span> <span style="color:var(--highlight-variable)">//</span> <span style="color:var(--highlight-variable)">prints</span> <span style="color:var(--highlight-namespace)">10</span></code></span>

You should take advantage of a number of other modern features. The following are my most prominent few others:
 

Always assume that your system has been distributed

When writing parallel applications, your goal is to optimize the amount of work you do at the same time. If you have four cores available and your code can only use a single kernel, 75% of your potential is being wasted. This means that blocking and synchronous operations are the ultimate enemies of parallel computing. But considering that JS is a single threaded language, things will not run on multiple kernels. What's the point?

JS is a single thread, but not a single file (such as in the school line)
). Even if it is not parallel, it is still concurrent. Sending an HTTP request can take seconds or even minutes, so if JS stops executing code until the request replies, the language will not be available. JavaScript pass event loop To solve this problem.



The event loop loops through the registered events and executes them according to the internal scheduling / priority logic. This can send thousands of HTTP requests at the same time or read multiple files from disk. The key is that JavaScript can only use this function when using the correct function. The simplest example is a loop:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-variable)">let</span> <span style="color:var(--highlight-variable)">sum</span> <span style="color:var(--highlight-variable)">=</span> <span style="color:var(--highlight-namespace)">0</span><span style="color:var(--highlight-variable)">;</span>
<span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">myArray</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>, <span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>, <span style="color:var(--highlight-namespace)">5</span>, <span style="color:var(--highlight-variable)">...</span> <span style="color:var(--highlight-namespace)">99</span>, <span style="color:var(--highlight-namespace)">100</span>]<span style="color:var(--highlight-variable)">;</span>
<span style="color:var(--highlight-variable)">for</span> <span style="color:var(--highlight-variable)">(let</span> <span style="color:var(--highlight-variable)">i</span> <span style="color:var(--highlight-variable)">=</span> <span style="color:var(--highlight-namespace)">0</span><span style="color:var(--highlight-variable)">;</span> <span style="color:var(--highlight-variable)">i</span> <span style="color:var(--highlight-variable)"><</span> <span style="color:var(--highlight-variable)">myArray.length;</span> <span style="color:var(--highlight-variable)">i</span> <span style="color:var(--highlight-variable)">+=</span> <span style="color:var(--highlight-namespace)">1</span><span style="color:var(--highlight-variable)">)</span> {
  <span style="color:var(--highlight-variable)">sum</span> <span style="color:var(--highlight-variable)">+=</span> <span style="color:var(--highlight-variable)">myArray</span>[<span style="color:var(--highlight-variable)">i</span>]<span style="color:var(--highlight-variable)">;</span>
}</code></span>

Vanilla ring is one of the most non parallel constructions in programming. In my last job, I led a team to spend several months trying to convert the traditional lang rotation into automatic parallel code. This is basically an unsolvable problem, which can only be solved by waiting for in-depth learning to improve. The difficulty of parallel circulation stems from some problematic patterns. Ring order is very rare, but this alone cannot guarantee the decomposability of rings: R

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-symbol)">let</span> runningTotal = <span style="color:var(--highlight-namespace)">0</span>;
<span style="color:var(--highlight-symbol)">for</span> (let i = <span style="color:var(--highlight-namespace)">0</span>; <span style="color:var(--highlight-symbol)">i</span> < myArray.length; <span style="color:var(--highlight-symbol)">i</span> += <span style="color:var(--highlight-namespace)">1</span>) {
  <span style="color:var(--highlight-symbol)">if</span> (i === <span style="color:var(--highlight-namespace)">50</span> && runningTotal > <span style="color:var(--highlight-namespace)">50</span>) {
    <span style="color:var(--highlight-symbol)">runningTotal</span> = <span style="color:var(--highlight-namespace)">0</span>;
  }
  <span style="color:var(--highlight-symbol)">runningTotal</span> += Math.random() + runningTotal;
}</code></span>

This code generates the expected results only when executed sequentially and iteratively. If you try to perform multiple iterations at the same time, the processor may branch incorrectly based on inaccurate values, invalidating the results. If this is C code, we will have different conversations. Because of different use cases, the compiler can use loops to do quite a lot of tricks. In JavaScript, traditional rings should be used only when absolutely necessary. Otherwise, use the following structure:



Map

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-comment)">// in decreasing relevancy :0</span>
<span style="color:var(--highlight-keyword)">const</span> urls = [<span style="color:var(--highlight-variable)">'google.com'</span>, <span style="color:var(--highlight-variable)">'yahoo.com'</span>, <span style="color:var(--highlight-variable)">'aol.com'</span>, <span style="color:var(--highlight-variable)">'netscape.com'</span>];
<span style="color:var(--highlight-keyword)">const</span> resultingPromises = urls.map((url) => makHttpRequest(url));
<span style="color:var(--highlight-keyword)">const</span> results = <span style="color:var(--highlight-keyword)">await</span> <span style="color:var(--highlight-literal)">Promise</span>.all(resultingPromises);</code></span>

Indexed map

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-comment)">// in decreasing relevancy :0</span>
<span style="color:var(--highlight-keyword)">const</span> urls = [<span style="color:var(--highlight-variable)">'google.com'</span>, <span style="color:var(--highlight-variable)">'yahoo.com'</span>, <span style="color:var(--highlight-variable)">'aol.com'</span>, <span style="color:var(--highlight-variable)">'netscape.com'</span>];
<span style="color:var(--highlight-keyword)">const</span> resultingPromises = urls.map((url, index) => makHttpRequest(url, index));
<span style="color:var(--highlight-keyword)">const</span> results = <span style="color:var(--highlight-keyword)">await</span> <span style="color:var(--highlight-literal)">Promise</span>.all(resultingPromises);</code></span>

For each

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-keyword)">const</span> urls = [<span style="color:var(--highlight-variable)">'google.com'</span>, <span style="color:var(--highlight-variable)">'yahoo.com'</span>, <span style="color:var(--highlight-variable)">'aol.com'</span>, <span style="color:var(--highlight-variable)">'netscape.com'</span>];
<span style="color:var(--highlight-comment)">// note this is non blocking</span>
urls.forEach(<span style="color:var(--highlight-keyword)">async</span> (url) => {
  <span style="color:var(--highlight-keyword)">try</span> {
    <span style="color:var(--highlight-keyword)">await</span> makHttpRequest(url);
  } <span style="color:var(--highlight-keyword)">catch</span> (err) {
    <span style="color:var(--highlight-literal)">console</span>.log(<span style="color:var(--highlight-variable)">`<span style="color:var(--highlight-color)">${err}</span> bad practice`</span>);
  }
});</code></span>

I will explain why these are improvements over traditional loops. Constructs, such as receiving all elements and submitting them as a single event to a user-defined map function, rather than performing each iteration in sequence. In most cases, individual iterations have no internal relationship or dependence on each other, so they can run at the same time. This is not to say that you can't do the same thing and cycle. In fact, it looks like this: map

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">items</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">0</span>, <span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>, <span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>, <span style="color:var(--highlight-namespace)">5</span>, <span style="color:var(--highlight-namespace)">6</span>, <span style="color:var(--highlight-namespace)">7</span>, <span style="color:var(--highlight-namespace)">8</span>, <span style="color:var(--highlight-namespace)">9</span>]<span style="color:var(--highlight-variable)">;</span>

<span style="color:var(--highlight-variable)">async</span> <span style="color:var(--highlight-variable)">function</span> <span style="color:var(--highlight-variable)">testCall()</span> {
  <span style="color:var(--highlight-variable)">//</span> <span style="color:var(--highlight-variable)">do</span> <span style="color:var(--highlight-variable)">async</span> <span style="color:var(--highlight-variable)">stuff</span> <span style="color:var(--highlight-variable)">here</span>
}

<span style="color:var(--highlight-variable)">for</span> <span style="color:var(--highlight-variable)">(let</span> <span style="color:var(--highlight-variable)">i</span> <span style="color:var(--highlight-variable)">=</span> <span style="color:var(--highlight-namespace)">0</span><span style="color:var(--highlight-variable)">;</span> <span style="color:var(--highlight-variable)">i</span> <span style="color:var(--highlight-variable)"><</span> <span style="color:var(--highlight-namespace)">10</span><span style="color:var(--highlight-variable)">;</span> <span style="color:var(--highlight-variable)">i</span> <span style="color:var(--highlight-variable)">+=</span> <span style="color:var(--highlight-namespace)">1</span><span style="color:var(--highlight-variable)">)</span> {
  <span style="color:var(--highlight-variable)">testCall();</span>
}</code></span>

As you can see, the loop doesn't prevent me from doing it the right way, but it certainly won't make it easier. Compared to the map version:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">items</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">0</span>, <span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>, <span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>, <span style="color:var(--highlight-namespace)">5</span>, <span style="color:var(--highlight-namespace)">6</span>, <span style="color:var(--highlight-namespace)">7</span>, <span style="color:var(--highlight-namespace)">8</span>, <span style="color:var(--highlight-namespace)">9</span>]<span style="color:var(--highlight-variable)">;</span>
<span style="color:var(--highlight-variable)">items.map(async</span> <span style="color:var(--highlight-variable)">(item)</span> <span style="color:var(--highlight-variable)">=></span> {
 <span style="color:var(--highlight-variable)">//</span> <span style="color:var(--highlight-variable)">do</span> <span style="color:var(--highlight-variable)">async</span> <span style="color:var(--highlight-variable)">stuff</span> <span style="color:var(--highlight-variable)">here</span>
}<span style="color:var(--highlight-variable)">);</span></code></span>

As you can see, it's just work. If you want to block until all individual asynchronous operations are completed, the advantages of maps become more obvious. With the loop code, you need to manage an array yourself. Here is the version: mapmap

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">items</span> <span style="color:var(--highlight-variable)">=</span> [<span style="color:var(--highlight-namespace)">0</span>, <span style="color:var(--highlight-namespace)">1</span>, <span style="color:var(--highlight-namespace)">2</span>, <span style="color:var(--highlight-namespace)">3</span>, <span style="color:var(--highlight-namespace)">4</span>, <span style="color:var(--highlight-namespace)">5</span>, <span style="color:var(--highlight-namespace)">6</span>, <span style="color:var(--highlight-namespace)">7</span>, <span style="color:var(--highlight-namespace)">8</span>, <span style="color:var(--highlight-namespace)">9</span>]<span style="color:var(--highlight-variable)">;</span>
 <span style="color:var(--highlight-variable)">const</span> <span style="color:var(--highlight-variable)">allResults</span> <span style="color:var(--highlight-variable)">=</span> <span style="color:var(--highlight-variable)">await</span> <span style="color:var(--highlight-variable)">Promise.all(items.map(async</span> <span style="color:var(--highlight-variable)">(item)</span> <span style="color:var(--highlight-variable)">=></span> {
  <span style="color:var(--highlight-variable)">//</span> <span style="color:var(--highlight-variable)">do</span> <span style="color:var(--highlight-variable)">async</span> <span style="color:var(--highlight-variable)">stuff</span> <span style="color:var(--highlight-variable)">here</span>
 }<span style="color:var(--highlight-variable)">));</span></code></span>
<span style="color:#3c4146">
<em>it's really that easy</em>
</span>

In many cases, a loop will perform the same (or possibly more) than, or. I still think it's worth losing a few cycles now to use a well-defined API. In this way, any future improvements to the implementation of the data access pattern will benefit your code. It is too generic for loops to meaningfully optimize the same pattern.
In addition to maps and preselections, there are other valid asynchronous options, such as waiting options.

mapforEach
 

Modify your code and enforce styles

Code without a consistent style (look and feel) is incredibly difficult to read and understand. Therefore, a key aspect of writing high-end code in any language is a consistent and sensible style. Due to the breadth of JS ecosystem, there are many choices of fluff and style details. I can't emphasize enough that you use fluff and enforce a style (any of them) is much more important than the lint / style you specifically choose. In the final analysis, no one will write code my way, so optimizing for this is an unrealistic goal. I see a lot of people asking them what they should use Esslint still More beautiful.



For me, they serve very different purposes, so they should be used together. ERINT is traditional fluff in most cases. It will identify problems with your code that have little to do with style and have to do with correctness. For example, I use and AirBNB Regular slashes. With this configuration, the following code will force the system to fail:

<span style="color:var(--highlight-color)"><code><span style="color:var(--highlight-symbol)">var</span> fooVar = <span style="color:var(--highlight-namespace)">3</span>; // airbnb rules forebid <span style="color:var(--highlight-variable)">"var"</span></code></span>

It should be clear how eslint adds value to your development cycle. Essentially, it ensures that you follow the rules about what is good and what is not. Because of this, lint people are born with opinions. Like all opinions, take a grain of salt. Lint may be wrong.
More beautiful is a code format
Device. It is less concerned about correctness and more concerned about unity and consistency. More beautiful won't complain about using, but it will automatically align all parentheses in your code. In my personal development process, I always make the last step more beautiful before pushing the code to Git. In many cases, it is more beautiful and even meaningful to automatically run each time it is submitted to the repurchase. This ensures that all code entering source control has a consistent style and structure. var


Test your code

Writing tests are an indirect but incredibly effective way to improve the JS code you write. I suggest using various testing tools to adapt. Your testing needs will vary, and no single tool can handle all problems. There are many mature testing tools in JS ecosystem, so the choice of tools mainly comes down to personal taste. As usual, think for yourself.



Test driver – EVA

<span style="color:#3c4146">
<a data-cke-saved-href="https://github.com/avajs" href="https://github.com/avajs">AvaJS on Github</a>
</span>

The test driver is just a framework that keeps the structure and utilities at a very high level. They are often used in conjunction with other specific testing tools that vary depending on your testing needs.
EVA is the right person for expressiveness and brevity
Balance. EVA's parallel and isolated buildings are my favorite source. Faster tests can save developers time and company money. Ava has a lot of good features, such as built-in assertions, while trying to keep it very small.
Substitutes: jester, mocha, Mo
Lihua



Spies and stubs Sinon


Sinon of gitubu

Spies provides us with function analysis, such as the number of times a function is called, what they are called, and other insightful data.

Sinon is a library that does a lot of things, but only a few super
OK. Specifically, Sinon is good at espionage and stubs. The feature set is rich, but the syntax is concise. This is particularly important for stubs because they exist partially to save space.

 



MOX Nock

Github

Nock on http simulation is a process of forging some parts of the http request process, so that the test program can inject custom logic to simulate server behavior.

Http ridicule may be a real pain, but nock makes it less painful
pain. Nock directly overwrites the built-in nodes and intercepts outgoing http requests. This in turn gives you complete control over the response.


Don't know any request s



Network automation - uranium

Gitub

I have mixed feelings about recommending uranium. Because it is the most popular option for network automation, it has a huge set of communities and online resources. Unfortunately, the learning curve is quite steep, and it depends on the actual use of a large number of external libraries. That is to say, this is the only real free option, so unless you are doing some enterprise level network automation, Selenium will do the work.
Alternative: cypress,
phantom


An endless journey

As with most things, writing better JavaScript is a continuous process. Code can always be cleaner, new features are added all the time, and there will never be enough testing. This may seem overwhelming, but with so many potential areas for improvement, you can really move forward at your own pace. Step by step, before you know, you will become the trump card of JavaScript.
This article originally appeared on Ruilan's personal website and Dev.to.

Keywords: Python Java Javascript Programming AI

Added by mastercjb on Thu, 10 Feb 2022 09:30:29 +0200