RxJS subcribe is deprecated - rxjs

I have trouble with subcribe method. In vscode it says that subcribe is deprecated but I have no clue how to change it properly.
public getAccount(): void{
this.accountService.getAccounts().subscribe(
(response: Account[]) => {
this.accounts = response;
},
(error: HttpErrorResponse) => {
alert(error.message);
}
)
}

You should pass an observer object instead of multiple callbacks. All signatures that used multiple arguments were deprecated.
this.accountService.getAccounts().subscribe({
next: (response: Account[]) => {
this.accounts = response;
},
error: (error: HttpErrorResponse) => {
alert(error.message);
},
complete: () => {
// do something when the observable completes
}
});
If you don't need an error and complete callbacks, you can still use it like this: .subscribe((value) => console.log(value)).
You can read about why the signature you're using was deprecated here.

Related

error Policy in Apollo Client React does'nt work

I have aproblem when test Apollo.When I try query with apollo and graphql, i want response return error and partical data, so I set property errorPolicy:'all'. But its not work. I don't no why? Help please!
Here my code:
query { animal {
name
age }, school {
name
numberfd } } `
const { loading,data,error} = useQuery(GET_DASHBOARD_DATA, {
errorPolicy:'all',
onCompleted: (res) => {console.log("complete",res)},
onError : (res,data) => {console.log("ERRRR",res,data)},
})
and i want to receive:
{
error:[...], data:[animal:[...]] }
but its only response error.Here is Apollo's doc: https://www.apollographql.com/docs/react/data/error-handling/
onError type is onError?: (error: ApolloError) => void;. You don't have data inside onError callback.
After useQuery you can add:
console.log('data', data)
console.log('error', error)
I faced the same issue with errorPolicy: 'all', I only received the partial result inside onCompleted callback of useQuery, but no errors.
I created an ErrorLink like this:
private createErrorLink = () => {
return new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
// filter out errors you don't want to display
const errors = filterSomeErrors(response.errors);
if (errors && response?.data) {
response.data.errors = errors;
}
return response;
});
});
};
Now inside my onCompleted callback I get my data as well as errors. You will have to tweak your types a bit, because seems there is no errors field on response.data by default.
Mind that if you use onError from Apollo and return something from the link, it will retry your request containing errors!

rxjs catcherror appening before pipe

I found some strange behavior on rxjs and I want to know if it's the expected behavior or if I missed something (I use angular but I thing it's not related) :
public someFunction() {
// this woks as expected: log "test1"
return of(null).pipe(
switchMap(() => this.errorTest()),
catchError((e: Error) => {
console.log('test1');
return throwError(e);
})
);
// "test2" is never logged
return this.errorTest().pipe(
catchError((e: Error) => {
console.log('test2');
return throwError(e);
})
);
}
private errorTest(): Observable<any> {
throw Error('one error');
}
when I subscribe someFunction the first function logs "test1", but the second doesn't log anything, error is no catched...
private errorTest(): Observable<any> {
throw Error('one error');
}
Does not return an observable.
switchMap(() => this.errorTest())
Catches errors from the callback function.
switchMap(() => throw Error('one error'))
Is the same as your example, and this.errorTest().pipe() never returns so you don't get an error for trying to call .pipe() on undefined.
What you wanted to do was this.
private errorTest(): Observable<any> {
return throwError(new Error('one error'));
}
https://rxjs-dev.firebaseapp.com/api/index/function/throwError

RxJS do not throw error while mapping even when underlying observable throws error

I have a network call where it's likely that api will throw an 400 error. I want to handle this gracefully.
Right now I do it like below -
private fetchStatus(objectId: string): Observable<string> {
return Observable.create((observer) => {
this.http.get('/api/data-one').subscribe(response => {
if (response.result === 'SUCCESS') {
observer.next('SUCCESS');
} else {
observer.next('DENIED');
}
observer.complete();
},
error => {
observer.next('DENIED');
observer.complete();
});
});
}
But I will prefer doing it with Observable.map operator. The problem with Observable.map is when api throws a 400 the entire observable goes in error mode.
I want to prevent this because this get call is being used in a forkJoin with other calls. Failure of this would mean failure of the entire forkJoin below
forkJoin([
this.http.get('/api/route-2'),
this.http.get('/api/route-1'),
this.fetchStatus('abc')
]).subscribe((responseCollection: any) => {
observer.next({
result1: responseCollection[0],
result2: responseCollection[1],
result3: responseCollection[2]
});
observer.complete();
}, error => observer.error(error));
You can do this with map and catchError.
catchError will catch any error thrown by the source and return a new Observable. This new Observable is what, in your case, will be passed to forkJoin in the case of a HTTP error.
private fetchStatus(objectId: string): Observable<string> {
return this.http.get('/api/data-one').pipe(
map(response => response.result === 'SUCCESS' ? 'SUCCESS' : 'DENIED'),
catchError(error => of('DENIED')),
);
}

RXJS: How to throttle Observable from Promise

I am using RxJS 5.5.10.
I try to throttle an observable to fire every 5 seconds.
This Observable is based on a Promise.
Rx.Observable.fromPromise(mongo.AllWishes)
.flatMap(array => Rx.Observable.from(array))
.pluck('url')
.filter(s => s !== undefined)
.subscribe(m => console.log(m))
I understand that I can use the throttle operator to emit values only after a given time
Rx.Observable.interval(1000)
.throttle(val => Rx.Observable.interval(5000)
.subscribe(m => console.log('ping'))
But when I try something like
Rx.Observable.fromPromise(mongo.AllWishes)
.throttle(val => Rx.Observable.interval(5000))
.flatMap(array => Rx.Observable.from(array))
.pluck('url')
.filter(s => s !== undefined)
.subscribe(m => console.log(m))
I get an error
rxjs/observable/PromiseObservable.js:76
root_1.root.setTimeout(function () { throw err; });
^
TypeError: this.durationSelector is not a function
What am I missing ?
Thank your for your help
I'm not entirely clear on your expectations. It looks like you are getting an array from a promise and are then wanting to emit each value sequentially with 5 seconds in-between each item.
If so, I think that this should do what you want. As far as your error it is hard to tell without being able to run your code. I'm assuming it has something to do with your promise since I can replace mongo.AllWishes with my own promise and it doesn't error.
const data = [
{ url: 'https://something.com/1' },
{ url: 'https://something.com/2' },
{ url: 'https://something.com/3' },
{ url: 'https://something.com/4' },
{ url: 'https://something.com/5' }
];
const myPromise = new Promise((resolve) => {
setTimeout(() => { resolve(data); }, 1000);
});
Rx.Observable.fromPromise(myPromise)
.flatMap(x => {
return Rx.Observable.timer(0, 1000)
.takeWhile(i => i < x.length)
.map(i => x[i]);
})
.pluck('url')
.subscribe((url) => { console.log(url); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.10/Rx.min.js"></script>

Observable from Subject

I'm trying to create actions from updates from a RX Subject
It's working but I get the error below.
Here is my Epic
export function uploadSceneFile(action$, store) {
return action$.ofType(CREATE_SCENE_SUCCESS)
.mergeMap(({payload}) =>
UploadSceneWithFile(payload)
.subscribe(res => {
if (res.progress > 0)
store.dispatch(uploadSceneProgress(res))
else if(res.progress === -1){
store.dispatch(uploadSceneSuccess(res))
requestSceneProcessing(res).map(res => {
})
}
})
)
}
And here is the Subject
export function UploadSceneWithFile(scene){
const subject$ = new Subject()
const uploader = new S3Upload({
getSignedUrl: getSignedUrl,
uploadRequestHeaders: {'x-amz-acl': 'public-read'},
contentType: scene.file.type,
contentDisposition: 'auto',
s3path: 'assets/',
onError:()=>subject$.next('error'),
onProgress: (val)=> subject$.next({...scene,progress:val}),
onFinishS3Put: ()=>subject$.next({...scene,progress:-1}),
})
uploader.uploadFile(scene.file)
return subject$
}
I read from a previous post that I'm supposed to be using .map, not .subscribe but nothing happens if I don't subscribe (the upload doesn't happen)
What's the best way of doing this?
subscribeToResult.js:74 Uncaught TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.subscribeToResult (subscribeToResult.js:74)
at MergeMapSubscriber../node_modules/rxjs/operators/mergeMap.js.MergeMapSubscriber._innerSub (mergeMap.js:132)
at MergeMapSubscriber../node_modules/rxjs/operators/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:129)
at MergeMapSubscriber../node_modules/rxjs/operators/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:112)
at MergeMapSubscriber../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at FilterSubscriber../node_modules/rxjs/operators/filter.js.FilterSubscriber._next (filter.js:89)
at FilterSubscriber../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at Subject../node_modules/rxjs/Subject.js.Subject.next (Subject.js:55)
at createEpicMiddleware.js:60
at createEpicMiddleware.js:59
at SafeSubscriber.dispatch [as _next] (applyMiddleware.js:35)
at
The problem is that you subscribe inside mergeMap and return a Subscription which is invalid. The callback needs to return only Observable, Promise, Array, or Iterable.
I'm not sure what exactly you need to do but if you need to perform some side-effects you can use do() operator instead of subscribing.
export function uploadSceneFile(action$, store) {
return action$.ofType(CREATE_SCENE_SUCCESS)
.mergeMap(({ payload }) => UploadSceneWithFile(payload)
.do(res => {
...
})
)
}
Or it looks like you could put do after mergeMap as well:
export function uploadSceneFile(action$, store) {
return action$.ofType(CREATE_SCENE_SUCCESS)
.mergeMap(({ payload }) => UploadSceneWithFile(payload))
.do(res => {
...
});
}

Resources