How to subscribe the observable? [duplicate] - javascript

When I run the linter it says:
subscribe is deprecated: Use an observer instead of an error callback
Code from this angular app:
this.userService.updateUser(data).pipe(
tap(() => {bla bla bla})
).subscribe(
this.handleUpdateResponse.bind(this),
this.handleError.bind(this)
);
Don't know exactly what should I use and how...
Thanks!

subscribe isn't deprecated, only the variant you're using is deprecated. In the future, subscribe will only take one argument: either the next handler (a function) or an observer object.
So in your case you should use:
.subscribe({
next: this.handleUpdateResponse.bind(this),
error: this.handleError.bind(this)
});
See these GitHub issues:
https://github.com/ReactiveX/rxjs/pull/4202
https://github.com/ReactiveX/rxjs/issues/4159

Maybe interesting to note that the observer Object can also (still) contain the complete() method and other, additional properties. Example:
.subscribe({
complete: () => { ... }, // completeHandler
error: () => { ... }, // errorHandler
next: () => { ... }, // nextHandler
someOtherProperty: 42
});
This way it is much easier to omit certain methods. With the old signature it was necessary to supply undefined and stick to the order of arguments. Now it's much clearer when for instance only supplying a next and complete handler.

For me, it was just the typescript version my VSCode was pointing to.
Got help from this GitHub comment.
I believe this is a typescript issue. Something in the newest versions of typescript is causing this warning to display in vs code. I was able to get it to go away by click the version of typescript in the bottom right corner of vs code and then choosing the select typescript version option. I set it to the node_modules version we have installed in our angular project which in our case happens to be 4.0.7. This caused the warnings to go away.

Find the details at official website
https://rxjs.dev/deprecations/subscribe-arguments
Notice the {} braces in second subscribe code below.
import { of } from 'rxjs';
// recommended
of([1,2,3]).subscribe((v) => console.info(v));
// also recommended
of([1,2,3]).subscribe({
next: (v) => console.log(v),
error: (e) => console.error(e),
complete: () => console.info('complete')
})

You can get this error if you have an object typed as Observable<T> | Observable<T2> - as opposed to Observable<T|T2>.
For example:
const obs = (new Date().getTime() % 2 == 0) ? of(123) : of('ABC');
The compiler does not make obs of type Observable<number | string>.
It may surprise you that the following will give you the error Use an observer instead of a complete callback and Expected 2-3 arguments, but got 1.
obs.subscribe(value => {
});
It's because it can be one of two different types and the compiler isn't smart enough to reconcile them.
You need to change your code to return Observable<number | string> instead of Observable<number> | Observable<string>. The subtleties of this will vary depending upon what you're doing.

I migrated my Angular project from TSLint to ESLint and it is now not showing the warning anymore!
I followed these steps. (End of each step I also recommend to commit the changes)
Add eslint:
ng add #angular-eslint/schematics
Convert tslint to eslint:
ng g #angular-eslint/schematics:convert-tslint-to-eslint
Remove tslint and codelyzer: npm uninstall -S tslint codelyzer
If you like to auto fix many of the Lint issues
ng lint --fix (It will also list the not fixed issues)
In VSCode uninstall the TSLint plugin, install ESLint plugin and Reload the VSCode.
Make sure it updated the package and package-lock files. Also the node_modules in your project.
If you have the tsconfig.json files under sub directory - you need to add/update the projects-root-directory/.vscode/settings.json with the sub directory where the tsconfig files are!
{
"eslint.workingDirectories": [
"sub-directory-where-tsconfig-files-are"
]
}
Information at VS Code official Page: Migrate from TSLint to ESLint (Thanks for pointing this out in the comment!)
Angular migrate from TSLint to ESLint Reference

I was getting the warning because I was passing this to subscribe:
myObs.subscribe(() => someFunction());
Since it returns a single value, it was incompatible with subscribe's function signature.
Switching to this made the warning go away (returns null/void);
myObs.subscribe(() => {
someFunction();
});

You should replace tslint with eslint.
As TSLint is being deprecated it does not support the #deprecated syntax of RXJS. ESLint is the correct linter to use, to do subscribe linting correctly.

The new Way of using RxJS is quit simple:
previous versions:
this.activatedRoute.queryParams.subscribe(queryParams => {
console.log("queryParams, queryParams)
}, error => {
})
New Version:
this.activatedRoute.queryParams.subscribe(
{
next: (queryParams) => {
console.log('queryParams', queryParams);
},
error: (err: any) => { },
complete: () => { }
}
);

Subscribe isn't deprecated.
So you should use:
import { of } from 'rxjs';
.subscribe({
next: (n) => console.log(n),
error: (e) => console.error(e),
complete: () => console.info('complete')
})

Related

Why is this code causing a parsing error when using the coalesce operator

I am not sure what I updated in my React project, but I started getting a parsing error trying to build my project. I am certain (honestly) that this worked fine some time in the recent past. (source file is a .tsx file) Thoughts?
const titles = new Map<number, string>();
resources.forEach((e: any) => {
// titles.set(
// e.StoreHierarchyValueId ?? e.SkuHierarchyValueId, e.Value
// )
if (e.StoreHierarchyValueId)
titles.set(e.StoreHierarchyValueId, e.Value);
else
titles.set(e.SkuHierarchyValueId, e.Value);
});
When I had the commented out code in place, "npm run build" would error out with the following less than helpful (to me) message:
Module parse failed: Unexpected token (51:822)
You may need an appropriate loader to handle this file type.
| // []
| // );
function retrieveCustomerResources(){console.log('"',env,'", "',customer,'"');if(env!==''&&env!==undefined&&customer!==''&&customer!==undefined){setLoadingResources(true);axios.get("/"+props.urlPart+"Hierarchy/"+env+"/"+customer).then(function(response){setResources(response.data);}).catch(function(error){console.log(error);}).then(function(){setLoadingResources(false);});}}if(env==="")return/#PURE/React.createElement("div",null,"No HT environment seleted");if(loadingResources){return/#PURE/React.createElement("div",null,"Loading "+props.urlPart+" Data for..."+customer);}if(resources===null||resources.length===0){return/#PURE/React.createElement("div",null,"No "+props.urlPart+" Data for..."+customer);}var titles=new Map();resources.forEach(function(e){return titles.set(e.StoreHierarchyValueId??e.SkuHierarchyValueId,e.Value);});var parentMap=new Map();resources.forEach(function(f){f.subRows=[];parentMap.set(f.StoreHierarchyValueId??f.SkuHierarchyValueId,f.subRows);});resources.forEach(function(f,_i){var v=parentMap.get(f.ParentId);if(!v){parentMap.set(f.ParentId,[f]);}else{v.push(f);}});var data=resources.filter(function(e){return e.ParentId===0;});// function Table({ columns, data, renderRowSubComponent }
| // : { columns: any, data: any, renderRowSubComponent: any }
| // ): any {
The problematic code was no where near line 51. The only way I figured this out was by commenting out sections of code until it compiled successfully.
Thanks to #Mike'Pomax'Kamermans and #epascarello. It was definitely my tooling options.
I was using eslint and typescript. My .tsconfig file had a target of "es5" (not sure how that got set, but anyways...) Once I changed it to ES6, the problem naturally went away.

VSCode Typescript intellisense wrong

I have been trying to create ServiceWorker for my website using SvelteKit, but am running into an issue here. I created a file /src/service-worker.ts and in there, I put the following code
import { build, files, prerendered, version } from '$service-worker';
const applicationCache = `applicationCache-v${version}`;
const staticCache = `staticCache-v${version}`;
const returnSSRpage = (path) =>
caches.open("ssrCache").then((cache) => cache.match(path));
// Caches the svelte app (not the data)
self.addEventListener("install", (event) => {
event.waitUntil(
Promise.all([
caches
.open("ssrCache")
.then((cache) => cache.addAll(["/"])),
caches
.open(applicationCache)
.then((cache) => cache.addAll(build)),
caches
.open(staticCache)
.then((cache) => cache.addAll(files))
])
.then(self.skipWaiting()),
)
})
... reduced code
When running npm run build this code compiles perfectly fine and the code runs in the browser. However, my VSCode intellisense gets some stuff wrong. Most notably, it says that the waitUntil property of event does not exist.
Property 'waitUntil' does not exist on type 'Event'.ts(2339) among other things, such as Property 'skipWaiting' does not exist on type 'Window & typeof globalThis'.ts(2339) and Cannot find name 'clients'.ts(2304).
Now, I am quite new to Javascript and Typescript, but from my experience, the Intellisense should not output an error that doesn't also appear during compilation. Why does this happen?
I am unsure of what information to provide. My TS version is 4.7.4 which is also the version VSCode is using for Intellisense. I have installed the ESLint extension for JS and TS.
What could be the problem here?
Thanks!
You can add "WebWorker" to the compilerOptions.lib in tsconfig.json and declare the type of self in the service worker file:
declare var self: ServiceWorkerGlobalScope;
This will lead to the event types automatically being inferred without further annotations via the event name.
You may need to restart the TS server (there is a command for that: TypeScript: Restart TS Server).
Still, odd that it would build as is...

i18next - " WebpackError: TypeError: namespaces.forEach is not a function" (hooks)

I'm trying to get i18next to work in my Gatsby project but I keep running into the below error whenever i try to build using yarn build.
From my package.json:
"i18next": "^19.8.2",
"react-i18next": "^11.7.3",
My i18n/index.js file:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// ...
i18n.use(initReactI18next).init({
fallbackLng: "en",
// have a common namespace used around the full app
ns: ["translations"],
defaultNS: "translations",
wait: true,
useSuspense: false
}, (err, t) => {
i18n.t('en');
});
// load additional namespaces after initialization
i18n.loadNamespaces('translations', (err, t) => {
i18n.t('i18n', { lng: 'en' } );
});
// i18n resource bundles for views
const i18nResourceBundlesViews = [
{
intro: {
en: { ...intro.en },
ja: { ...intro.ja },
},
},
// ...
];
// i18n resource bundles for components
const i18nResourceBundlesComponents = [
{
header: {
en: { ...header.en },
ja: { ...header.ja },
},
},
{
footer: {
en: { ...footer.en },
ja: { ...footer.ja },
},
},
];
// Load i18n resource bundles from each resource object
const getI18nResourceBundles = (resource) => {
const key = Object.keys(resource)[0];
const enBundle = resource[key].en;
const jaBundle = resource[key].ja;
// English translations
i18n.addResourceBundle('en', key, enBundle);
// Japanese translations
i18n.addResourceBundle('ja', key, jaBundle);
};
// i18n resource bundles for views
i18nResourceBundlesViews.forEach((resource) => {
getI18nResourceBundles(resource);
});
// i18n resource bundles for components
i18nResourceBundlesComponents.forEach((resource) => {
getI18nResourceBundles(resource);
});
export default i18n;
The full error message after yarn build
❯ yarn build
yarn run v1.22.5
$ gatsby build
success open and validate gatsby-configs - 0.044s
success load plugins - 0.800s
success onPreInit - 0.016s
success delete html and css files from previous builds - 0.027s
success initialize cache - 0.009s
success copy gatsby files - 0.154s
success onPreBootstrap - 0.020s
success createSchemaCustomization - 0.007s
success source and transform nodes - 1.225s
success building schema - 0.415s
success createPages - 0.021s
success createPagesStatefully - 0.104s
success onPreExtractQueries - 0.002s
success update schema - 0.052s
success extract queries from components - 0.418s
success write out requires - 0.008s
success write out redirect data - 0.005s
warn The icon(./static/favicon/favicon-512.png) you provided to 'gatsby-plugin-manifest' is not square.
The icons we generate will be square and for the best results we recommend you provide a square icon.
success Build manifest and related icons - 0.183s
success onPostBootstrap - 0.192s
⠀
info bootstrap finished - 6.260 s
⠀
warn Browserslist: caniuse-lite is outdated. Please run:
npx browserslist#latest --update-db
success Building production JavaScript and CSS bundles - 19.520s
success Rewriting compilation hashes - 0.010s
success run queries - 20.490s - 6/6 0.29/s
failed Building static HTML for pages - 4.770s
ERROR #95313
Building static HTML failed for path "/404/"
See our docs page for more info on this error: https://gatsby.dev/debug-html
37 | var _this = this;
38 |
> 39 | namespaces.forEach(function (ns) {
| ^
40 | if (!_this.usedNamespaces[ns]) _this.usedNamespaces[ns] = true;
41 | });
42 | }
WebpackError: TypeError: namespaces.forEach is not a function
- context.js:39 ReportNamespaces.addUsedNamespaces
node_modules/react-i18next/dist/es/context.js:39:1
- useTranslation.js:41 useTranslation
node_modules/react-i18next/dist/es/useTranslation.js:41:1
- index.jsx:27 Footer
src/components/theme/Footer/index.jsx:27:38
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
In my Footer/index.jsx where the error originally occurs (line 27):
const { t, i18n } = useTranslation({useSuspense: false});
Any help would be greatly appreciated. Thank you
This issue has been resolved.
Reference including the solution: https://github.com/benji011/portfolio.benjaminlo.io/pull/9#issuecomment-707612060
I think I've managed to pinpoint the two issues you were originally
having. I've uploaded the fixes I've made, please see if it builds for
you. It builds fine for me.
1. React suspense:
i18n appears to use Suspense but this is problematic for Gatsby. See
here.
The fix is quite straightforward and I've added it to the config.
2. The i18ncheck statement: ```const i18nCheck = i18n.languages.toLowerCase().includes('en') ||
i18n.languages.toLowerCase().includes('en-');```
This statement is problematic.
There are two variables that contain the languages.
language, which I think is the current language, and is set to a string: en
languages which is an array of languages. This is set to ['en', 'dev'].
If you want to check for the array languages, then we can't use
toLowerCase() like it was used. It will result in an error as we are
applying toLowerCase() on the entire array and not an element of the
array. toLowerCase() must be used on a string and won't ork on an
array. We would have to loop through the array and then apply
toLowerCase(). I don't think you were wanting to check the array
though as the language, for example 'en', would always be in the
array.
Another issue related to this is that i18n might not have the
property yet, so we need to check that it has the property first.
The best approach, imo, is to just check the language to see if it
is en or en-.
Regarding ESLint and Prettier:
You should use both.
ESLint is a linter and will show code errors. The project already has
an ESLint config, you just need the plugin. There might be a window
that pops up when you open the project, which you must then choose
Allow.
Prettier is a formatter and will format your code e.g. split up a long
line into 3 separate lines

How do I correctly configure mocha tests with ts_transformer_keys?

I can't seem to set the custom transformer for ts-transform-keys with my mocha tests.
I’m using mocha 6.1.4
ts-node 8.3.0 https://www.npmjs.com/package/ts-node
ts-trasnformer-keys 0.3.5 https://github.com/kimamula/ts-transformer-keys
ttypescript 1.5.7 https://github.com/cevek/ttypescript
The ts-node documentation says that you cannot set a custom transformer on the CLI, only programatically. So I'm trying to use ttypescript to get around that restriction.
I've tried the following...
Note: test.ts contains the following
import { keys } from 'ts-transformer-keys';
describe("xyz"), () => {
it("123", (done) => {
keys<CustomInterface>();
});
});
Attempt 1) - Set the ts-node with an environment variable
TS_NODE_COMPILER="ttypescript" mocha test/test.ts --require ts-node/register
Then I have the following in test/tsconfig.json
{
"compilerOptions": {
"plugins": [
{ "transform": "ts-transformer-keys/transformer" }
]
}
}
This results in Uncaught TypeError: ts_transformer_keys_1.keys is not a function which indicates that the custom transformer wasn't used at compile time.
Attempt 2) Following the typescript API example from ts-transformer-keys
I added a mocha.opts file with the following
--file test/transformer-config.js
and a transformer-config.js file with the following
const ts = require('typescript');
const keysTransformer = require('ts-transformer-keys/transformer').default;
const program = ts.createProgram(['test/test.ts'], {
strict: true,
noEmitOnError: true,
target: ts.ScriptTarget.ES5
});
const transformers = {
before: [keysTransformer(program)],
after: []
};
const { emitSkipped, diagnostics } = program.emit(undefined, undefined, undefined, false, transformers);
if (emitSkipped) {
throw new Error(diagnostics.map(diagnostic => diagnostic.messageText).join('\n'));
}
Then I invoke it like this mocha test/test.ts --require ts-node/register
This results in the following error
/Users/jjohnson/Documents/OCS/hmp/git/hmp-server/server/test/ttypescript-register.js:17
throw new Error(diagnostics.map(diagnostic => diagnostic.messageText).join('\n'));
^
Error: [object Object]
[object Object]
[object Object]
at Object.<anonymous> (/Users/jjohnson/Documents/OCS/hmp/git/hmp-server/server/test/ttypescript-register.js:17:9)
at Module._compile (internal/modules/cjs/loader.js:777:30)
...
It feels like in Attempt 1 it wasn't ever calling the code that sets the custom transformer in tsconfig.json or if it was getting called the code was failing silently.
It feels like in Attempt 2 I'm creating a new instance of the typescript program and then that fails for some reason. And even if it succeeded I'm not sure that this is the right way to go about configuring things since the ts.createProgram wants a list of RootNames for the files it will transpile.
Maybe my entire approach is wrong.
All I really want is a way that in my mocha tests I can verify that the expected result type is what the method returned. And I'd like to be able to do this w/out touching too much of the source code.
you should be able to define your required module (see below) and run ts-node programmatically. In this way, you can safely use any customer transformer.
// tsnode.js
const transformer = require('ts-transformer-keys/transformer').default;
require("ts-node").register({
transformers: program => ({
before: [
transformer(program)
]
})
});
then you can run mocha with require
mocha --require './tsnode.js' --watch-extensions ts,tsx "test/**/*.{ts,tsx}
You can tell ts-node which compiler to use in tsconfig.json. This is covered in the ts-node docs. If your using transformers presumably your also using ttypescript compiler. You just need to add this:
"ts-node": {
"compiler": "ttypescript"
}

React Syntax Error: Unexpected Token at =

ERROR in ./src/js/HomeView.js
Module build failed: SyntaxError: Unexpected token (122:19)
120 | }
121 |
> 122 | handleDrawerOpen = () => {
| ^
123 | this.setState({ open: true });
124 | };
125 |
Got the above error when trying to compile react component using webpack.
Does anyone know what is the missing plugin here?
You'll probably need to install preset-stage-2.
This babel plugin allows you to use ES6+ features such as statics, property initializers, and even dynamic import support.
You could actually just install transform-class-properties for this particular case, but I usually prefer to install a babel plugin with stage-x because I find it comfortable to use multiple ES6+ features with a single install.
It might also be useful to future readers that this particular Babel plugin is already properly set up for you if you use create-react-app, as you can check here.
Difficult to guess from the code you have pasted above.
My guess is change it to
handleDrawerOpen() {
this.setState({ open: true });
}

Categories

Resources