How to implement side effect on Observable retuned by HttpClient.get? - javascript

Does someone know how to use RxJS do operator on observer returned by angular's HttpClient.get method?
Versions:
angular: 5.2.1
rxjs: 5.5.6
With this version of angular I can't do this:
import { HttpClient } from '#angular/common/http';
...
constructor(
private http: HttpClient,
) { }
...
this.http.get<Item>(url)
.do(res => console.log(JSON.stringify(res)))
.share();
Instead I have to add new steps with pipes. I can do it with switchMap, map or share, but I can't figure out how to do it with do.
I found out that I can do import { _do } from 'rxjs/operator/do';, but when I'm trying to use it like this:
this.http.get<Item>(url)
.pipe(_do(res => console.log(JSON.stringify(res)))
or like this:
const observable = this.http.get<Item>(url);
observable.pipe(_do(observable, res => console.log(JSON.stringify(res)}));
I'm getting error:
[ts] The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<{}>'.

As pipeable operators documentation explains, pipeable do was renamed to tap, alongside with several others. This was done in order to avoid collisions with reserved JavaScript keywords.
Pipeable operators are supposed to be imported as
import { tap } from 'rxjs/operators/tap';
Notice that pipeable operators are located in rxjs/operators/..., while rxjs/operator/... imports are used to patch Observable.prototype.
There are no concerns that would prevent do operator from being used some Angular versions. Both import styles are supported and valid, as long as a developer understands that there are certain differences between patch operators and pipeable operators that make the latter preferable in some cases. They are explained on documentation page:
Any library that imports a patch operator will augment the Observable.prototype for all consumers of that library, creating blind
dependencies. If the library removes their usage, they unknowingly
break everyone else. With pipeables, you have to import the operators
you need into each file you use them in.
Operators patched directly onto the prototype are not "tree-shakeable" by tools like rollup or webpack. Pipeable operators
will be as they are just functions pulled in from modules directly.
Unused operators that are being imported in apps cannot be detected reliably by any sort of build tooling or lint rule. That
means that you might import scan, but stop using it, and it's still
being added to your output bundle. With pipeable operators, if you're
not using it, a lint rule can pick it up for you.
Functional composition is awesome. Building your own custom operators becomes much, much easier, and now they work and look just
like all other operators from rxjs. You don't need to extend
Observable or override lift anymore.

I fixed it with help of this answer.
Actually, I had wrong import. This code works:
import 'rxjs/add/operator/do';
...
this.http.get<Item>(url)
.do(res => console.log(JSON.stringify(res))

Related

What is the difference between `import Anything from #anywhere` and no import

When using autoimport feature of nuxt3:
is there any impact (types, performance, bundle-size, tree-shaking, etc..) of using the # alias to import something rather than no import at all?
Or its only purpose is to make imports explicit and maybe help to fix some IDE/linter/ts issues?
Example:
// plugins/vuetify.ts
import { createVuetify, VuetifyOptions } from "vuetify";
import { defineNuxtPlugin, NuxtApp, Plugin } from "#app"; // this line should be optional
export const VuetifyPlugin: Plugin = defineNuxtPlugin((nuxtApp: NuxtApp) => {
const vuetify = createVuetify();
nuxtApp.vueApp.use(vuetify);
});
export default VuetifyPlugin;
I wasn't aware of the # import, do you have a reference for that specifc one?
As you kinda guessed it, there are no direct benefits of making the imports yourself. In the same way that Nuxt does the job for you regarding ref, computed, watch etc, it will try to import most of the other common stuff.
The compiler will scan your file, see what you are using in your template + script part and make the import himself on runtime. It may not guess fully dynamic imports (usually for components based on a dynamic variable for example).
Still, it should work in the exact same way performance-wise.
For the types I know that there could be some limitations (not a full coverage), but since I don't use TS, I'm not well aware of all the details.
Regarding IDEs/code editors, most of the time they will work fine but some of them may require a bit of configuration to work perfectly (since it's implicit, you still need to tell your editor what is happening), otherwise some Linters may complain a bit.
Nuxt's auto import feature is probably based on something really similar (if not identical) to this: https://github.com/antfu/unplugin-auto-import
Hence, you can see in details how this one works to get more explanation.

Safe navigation operator in Reactjs using JSX

I am using Reactjs via JSX. Is there any safe navigation operator to use in this method? I tried using question mark operator like "foo?.bar" but I got syntax error.
The safe navigation operator (aka. Elvis operator) is a proposal in draft status with TC39, so no. Not yet anyway (as of this writing).
But this ugly syntax will get you there without a library. Instead of ...
foo?.bar
... use this ...
(foo||{}).bar||{}
It's hard to read but it works and it isn't dependent on a library.
UPDATE: The proposal has reached stage 4, so it will be part of ES2020.
You can use from get method in lodash library, like this:
import { get } from 'lodash';
get(foo, 'bar1.bar2.bar3.bar4');
Now, there is a babel plugin called #babel/plugin-proposal-optional-chaining that solves this problem.

Is using an ES6 import to load specific names faster than importing a namespace?

I've found at least two ways to import functions in from a module like Ramda for example. There are probably a few more ways to do something very similar like const R = require('ramda');
Option 1 is to import certain functions:
import { cond, T, always, curry, compose } from 'ramda';
Option 2 is to import the whole module like:
import * as R from "ramda";
I would prefer to reference the module from which the function is being called like so:
R.T();
But if the 2nd option is used, does it bring in every Ramda function not just the ones used in a module I'm working in? Are there any impacts on actual memory use, or bandwidth use as far as what gets sent to the browser if option 2 is used?
Is it possible to somehow do this:
// invalid syntax below:
import R { cond, T, always, curry, compose } from 'ramda';
R.T();
My question is kinda related to this one, but it's a bit different
import R (ramda) into typescript .ts file
TL;DR: It does not matter.
import * as … from 'ramda';
import { … } from 'ramda';
will both by default always bring in the complete Ramda module with all its dependencies. All code inside the module would be run, and which syntax was used to reference the exported bindings doesn't matter. Whether you use named or namespaced imports comes down to preference entirely.
What can reduce the file size to download and the used memory is static analysis. After having evaluated the module, the engine can garbage-collect those bindings that are referenced from nowhere. Module namespace objects might make this slightly harder, as anyone with access to the object can access all exports. But still those objects are specified in a way (as immutable) to allow static analysis on their usage and if the only thing you're doing with them is property access with constant names, engines are expected to utilise this fact.
Any size optimisation involves guessing which parts of the module need to be evaluated and which not, and happens in your module bundler (like Rollup or WebPack). This is known as Tree Shaking, dropping parts of the code and entire dependencies when not needed (used by anything that got imported). It should be able to detect which imports you are using regardless of the import style, although it might have to bail out when are doing unusual things with the namespace object (like looping it or using dynamic property access).
To learn about the exact guesses your bundler can make, contact its documentation.
#Bergi is right in his comment, which I think should be the answer. I would also like to point out you can always try things out in Babel to see what it compiles to: click here to see what an example destructuring actually does
So basically even if you destructure just one function from the module, the whole module will be required. In the Babel example I gave, I just extracted Component from the 'react' module, but the compiled code actually just required the whole thing. :)
Adding to #Bergi, Also just for future reference if you want to shed unused functions and import only the desired function, use selective import like below
import isEmpty from 'ramda/src/isEmpty';
This way you can complement it with Webpack and get a better tree shaking. Hope it helps

How to rename React components _and_ have the 'imports' refactored too?

When renaming a React component, how do you ensure the new name is used everywhere?
E.g. OldComponent -> NewComponent
The IDE I'm currently using (IntelliJ IDEA) only part does the job. For example, it will leave the variables with the old name in import statements:
import OldComponent from 'components/NewComponent.jsx'
...
<OldComponent />
Do people generally avoid refactoring in JS, or are there solutions/tools that can do this? (Or do people just kinda get used to manually refactoring? :D)
I think that Shift + F6 should do the job. It does the renaming for all matching cases. You could also find this in context menu -> Refactor -> Rename...
For me personally, the solution was to use TypeScript.
IntelliJ will automatically update the imports for you (if you use TypeScript).

When using ES6 import statement, is there a way to protect against items being undefined?

import {
foobar1,
foobar2,
foobor3, //typo! this key doesn't exist in the module.
} from './module_file.js'
console.log(foobar1, foobar2, foobar3) //EXPLODES
One of the most frequent silly mistakes I make when using the new ES6 style import statement is that I'll have a typo in one of the keys in object destructuring. I can't think of a single instance where I'd ever want a value in a destructuring assignment to be undefined. Is there any way to force the import statement to fail-fast if one of the items I'm trying to import is undefined?
ie:
import {
doesntExistInModule //EXPLODE NOW! 🔥🔥🔥
} from './module_file.js'
There is no hook allowing a module to run some code before its dependencies load. This means that modules have no control over how
their dependencies are loaded.
There is no error recovery for import errors. An app may have hundreds of modules in it, and if anything fails to load or link,
nothing runs. You can’t import in a try/catch block. (The upside here
is that because the system is so static, webpack can detect those
errors for you at compile time.)
For more details, read it out
The module stuff in the spec is pretty gnarly, but I believe a real implementation will throw a SyntaxError at 15.2.1.16.4 ModuleDeclarationInstantiation( ) Concrete Method step 12.d.iii in that case. Since there are no legit implementations I don't know if you're talking about a way to do it in transpiled code in the meantime, or if you don't realize that's the case and will be satisfied to know it'll work that way eventually. There's been talk before of trying to implement that kind of check in Babel, but as far as I know nothing's actually been done to that effect. Babel compiles each module in isolation.
Also, this is not object destructuring, it just has similar syntax.

Categories

Resources