Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not possible to use catch / filter / or any other RxJs Observable methods after setItem(...) #10

Closed
atiris opened this issue Sep 27, 2017 · 11 comments
Assignees
Labels

Comments

@atiris
Copy link

atiris commented Sep 27, 2017

Hi. How can I catch errors and transform it into Observable.of(false)?
Or how to use filter or any other Observable method from setItem('local-storage-variable', variable) observable? I want to use catch, but I try filter also and always with the same result:

Part of my code:

...
import { AsyncLocalStorage } from 'angular-async-local-storage';
import { Observable } from 'rxjs/Observable'; // I try it also from rxjs/Rx
import 'rxjs/add/operator/catch'; // I try it also without this line
...
@Injectable()
export class SessionService {
  constructor(
    private asyncLocalStorage: AsyncLocalStorage,
    ...
  ) { }
  public logout(): Observable<boolean> {
    return this.asyncLocalStorage.setItem('session', this.session)
      .filter(f => f === true) // error on this line
      .catch(err => Observable.of(false)); // error on this line if previous is commented
  }

Errors:
ERROR TypeError: this.asyncLocalStorage.setItem(...).filter is not a function
ERROR TypeError: this.asyncLocalStorage.setItem(...).catch is not a function
Versions in angular project: "angular-async-local-storage": "^2.0.0", "rxjs": "^5.4.3"

Thank you in advance very much for your help.

@cyrilletuzi
Copy link
Owner

Operators work fine, you just need to import each one, some are missing in your example :

import 'rxjs/add/operator/filter';
import 'rxjs/add/observable/of';

But what are you trying to do ? Because your example has no sense :

  • setItem is for saving data, it doesn't return any data, so there is nothing to filter here ;
  • errors catching is already done in the lib, if you want to catch the error you just have to put the second callback in your subscribe, see the example in the README (even if there is no real reason for local storage to fail).

@atiris
Copy link
Author

atiris commented Sep 27, 2017

Ok, you probably do not see such potential on this issue as I am :)

If your function returns RxJs Observable, it should be possible to use all methods defined in this class (even if it makes no sense to use them). As I wrote above, even with import of "of" and "filter" it is not possible to apply filter on your observable instance (please, try it!). Of course, the standard observable can be used to filter without any problems.

What I trying to do?
Just use filter and catch to observable instance (as any other observable instance from RxJs).

Example:

  • Yes, filter after setItem probably will never be used, but it does not change that it should be applicable as for any other instance of Observable.
  • I have seen the example in the README, but I want to capture all exceptions by my service. Any subscriber should not get any error value (or catch it).

For better example I created plunker also with get->catch (important when you want return the same type of value you subscribe) and get->filter->map (i think, filter is commonly used for stored values)

Running plunker here: https://plnkr.co/edit/xXfiqb4FKjzc4mIrTJEc?p=preview

Do you think using a filter to observable that returns console Error: filter is not a function is ok?

@cyrilletuzi
Copy link
Owner

cyrilletuzi commented Sep 27, 2017

I did try, or I wouldn't have closed the issue. This library just use normal Observables, there is nothing custom, so operators should work as usual.

I'll do some more research tomorrow, thanks for the plunker.

@cyrilletuzi cyrilletuzi reopened this Sep 27, 2017
@cyrilletuzi
Copy link
Owner

I can't reproduce your issues :

  • get/set examples with catch work fine,

  • filter example work fine without flatMap, that has no meaning here, except creating real errors as the next value is therefore an object, so it's normal subsequent actions fail.

Did you try your code in a TypeScript aware editor ? There are several RxJS errors in your code, for exemple :

  • Observable.from is for arrays/iterables, it is Observable.of for primitive values ;
  • in the filter example, it fails because of the error I told you, and it directly appears in TS when I copied your code...

@atiris
Copy link
Author

atiris commented Sep 28, 2017

I get this error only to console during runtime. I use Visual studio code and it does not see any problem when using the catch method after getItem() (no warning, no red underline..). getItem return Observable and catch can be applied to observable, so in code, no problem. But in runtime, I get error, and only from observable, created by your getItem method. Apply catch to any other observable throw no errors. That's weird.

In my original code i use Observable.of but I did not know how to do it on plunker, so I used Observable.from.

Ok for filter. it was just a test if it does for some other function than catch (and I found filter). My primary problem is catch. I wrote this plunker only in browser, so I apologize for a misleading example according to using flatMap and filter.

So, if you say that it works correctly, it means that you do not receive an error message in the console, like: .catch is not a function after observable returned by your asyncLocalStorage.getItem(...) method, when you click on "Catch Get FIXME" button?

I got this:

ERROR TypeError: this.asyncLocalStorage.getItem(...).catch is not a function
    at SessionService.alsGet (session.service.ts:22)
    at App.alsGet (app.ts:56)
    at Object.eval [as handleEvent] (App.html:11)
    at handleEvent (view.ts:142)
    at callWithDebugContext (services.ts:815)
    at Object.debugHandleEvent [as handleEvent] (services.ts:411)
    at dispatchEvent (util.ts:185)
    at eval (element.ts:238)
    at HTMLButtonElement.eval (dom_renderer.ts:75)
    at ZoneDelegate.invokeTask (zone.js:425)

@cyrilletuzi
Copy link
Owner

I do have the same error in console with your plunker, but when I reproduce the exact same scenario in a real app for testing, everything is OK.

I think it's a configuration/loading problem, but I can't see where...

@atiris
Copy link
Author

atiris commented Sep 28, 2017

Thanks for your effort.
Are you using Webpack or Systemjs?
My application use Webpack and I will try create full example out of plunker if it can be reproduced (but I can not guess when I'll have time for it).

@cyrilletuzi
Copy link
Owner

My demo app for testing is using Systemjs, and my real app is using webpack via the Angular CLI.

@atiris
Copy link
Author

atiris commented Oct 2, 2017

Hi, tihis is full steps for minimal application using Webpack and Angular CLI returned this error.
Tested twice, and this always leads to a bug in the console.
Please refer to your application created using the webpack if you see any differences in configuration. Or do you see the reason that I have something wrong and should not it work .catch method on this observable? I assume that if you have the same @angular/cli version, your application must return the same result (error).

ng --version: @angular/cli: 1.4.3, node: 8.4.0

Repro steps. Console:

ng new als-test
cd als-test
npm install angular-async-local-storage --save

Added to app.module.ts (only new parts of code):

import { AsyncLocalStorageModule } from 'angular-async-local-storage';
imports: [
    AsyncLocalStorageModule,

app.component.html (full content):

<button (click)="save()">Save</button>

app.component.ts (new content):

import { AsyncLocalStorage } from 'angular-async-local-storage';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';

constructor(protected localStorage: AsyncLocalStorage) { }
  // want to catch any error and return false instead of error
  public save() {
    let a: Observable<boolean>;
    a = Observable.of(true);
    a.catch(err => Observable.of(false));
    a.subscribe(() => { console.log('A test is done'); },
      () => { console.log('The test return error'); });

    let b: Observable<boolean>; // you can see both variables are same type
    b = this.localStorage.setItem('key', 'value');
    b.catch(err => Observable.of(false)); // but here you can not use catch
    b.subscribe(() => { console.log('Local storage observable test is done'); },
      () => { console.log('Local storage observable error'); });
  }

Run and test. Console: ng serve. Click on button save.
Result in console A observable is ok, B observable return error, even if both are variables of the same type:

A test is done
AppComponent.html:1 ERROR TypeError: b.catch is not a function
    at AppComponent.webpackJsonp.../../../../../src/app/app.component.ts.AppComponent.save (app.component.ts:25)
    at Object.eval [as handleEvent] (AppComponent.html:1)
    at handleEvent (core.es5.js:12023)
    at callWithDebugContext (core.es5.js:13493)
    at Object.debugHandleEvent [as handleEvent] (core.es5.js:13081)
    at dispatchEvent (core.es5.js:8615)
    at core.es5.js:9226
    at HTMLButtonElement.<anonymous> (platform-browser.es5.js:2651)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
    at Object.onInvokeTask (core.es5.js:3881)
View_AppComponent_0 @ AppComponent.html:1
proxyClass @ compiler.es5.js:15134
webpackJsonp.../../../core/@angular/core.es5.js.DebugContext_.logError @ core.es5.js:13433
webpackJsonp.../../../core/@angular/core.es5.js.ErrorHandler.handleError @ core.es5.js:1080
(anonymous) @ core.es5.js:9230
(anonymous) @ platform-browser.es5.js:2651
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:425
onInvokeTask @ core.es5.js:3881
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:192
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:499
invokeTask @ zone.js:1540
globalZoneAwareCallback @ zone.js:1566
AppComponent.html:1 ERROR CONTEXT DebugContext_ {view: {}, nodeIndex: 0, nodeDef: {}, elDef: {}, elView: {}}

@cyrilletuzi
Copy link
Owner

Fixed in 2.0.1.

Thanks for reporting this issue, your perseverance (sorry about the first closing) and your help to reproduce the issue. 👍

@atiris
Copy link
Author

atiris commented Oct 3, 2017

Many thanks for the fix, everything works now.

@cyrilletuzi cyrilletuzi self-assigned this Nov 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants