throw error inside rxjs Observable - javascript

I'm trying to throw an error inside a rxjs Observable
new Observable(subscriber => {
Observable.throw("error1");
return Observable.throw("error2");
})
.subscribe(
() => {},
err => console.error(err)
);
error 1 is not caught.
error2 gives a compilation error:
Argument of type '(this: Observable<{}>, subscriber: Subscriber<{}>) => ErrorObservable<string>' is not assignable to parameter of type '(this: Observable<{}>, subscriber: Subscriber<{}>) => TeardownLogic'. Type 'ErrorObservable<string>' is not assignable to type 'TeardownLogic'
what is the proper way to throw an error inside an observable?

Use Subscriber.error:
new Rx.Observable(subscriber => {
subscriber.error("error1");
subscriber.error("error2"); // not called because a stream will be finalized after any error
})
.subscribe(
() => {},
err => console.error(err)
);
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

When using new Observable() or Observable.create() you can push the error directly to the subscriber (observer):
Observable.create(subscriber => {
subscriber.error(new Error("error1"));
})
.subscribe(
() => {},
err => console.log(err.message)
);
The anonymous function passed to new Observable() can optionally return an unsubscribe callback. That's why it gives you the error because you're returning an Observable.
Using Observable.throw("error1") is usually not necessary. This is just an Observable that only emits an error and nothing more. You could use it for example like the following:
Observable.create(subscriber => {
subscriber.next('whatever');
})
.merge(Observable.throw(new Error("error2")))
.subscribe(
() => {},
err => console.log(err.message)
);
See live demo: https://jsbin.com/fivudu/edit?js,console

In v6 and higher you want to import throwError, that Observable.throw static method is an unfortunate necessity leftover from v5 compat.
import { throwError } from 'rxjs';
throwError('hello');
Source: https://github.com/ReactiveX/rxjs/issues/3733#issuecomment-391427430

With an observable you created yourself, you have access to the observer.error() method.
const obs = Observable.create(observer => {
// Emit a value.
observer.next("hello");
// Throw an error.
observer.error("my error");
});
Note: if you're using RxJS 4, you'll have to use onNext() and onError() instead.

Related

How do I fetch-mock an accurate server error?

The issue:
fetchmock
fetchMock.get('glob:https://*/server-api-uri', () => {
throw { example: 'error' }
})
Source JS file:
exampleServerCall().catch(error => {
console.log(error) // error = "[ object object ]" :(
})
So my catch statements are returning with a useless "[ object object ]" string when what I really want is access to the full mocked server error.
After reading the MDN docs for throw, I found documentation for how to throw a custom object in a throw handler.
You need to do it by creating a custom class object.
fetchmock
class CustomError {
example = 'error'
}
fetchMock.get('glob:https://*/server-api-uri', () => {
throw new CustomError()
})
source JS file:
exampleServerCall().catch(error => {
console.log(error) // error = { example: 'error' } :D
})

RxJS Error Observable when another emits value

Contrived example of what I'm trying to do here:
const source = interval(1000);
const errorWhenThisEmits = timer(2500);
source.pipe(/* someOperatorHere? */).subscribe({
next: () => console.log('next!'),
error: (err) => console.log(err)
});
// desired outcome:
// 1000ms: next!
// 2000ms: next!
// 2500ms: error message
Is it possible to cause the source observable to error when the second observable emits a value?
takeUntil gets close, but completes instead of errors.
You could merge the observables
const source = interval(1000);
const notifier = timer(2500).pipe(switchMap(() => throwError("error message")));
merge(source, notifier).subscribe({
next: () => console.log("next!"),
error: err => console.log(err)
});
See stackblitz: https://stackblitz.com/edit/rxjs-ony9vx?file=index.ts
Discovered takeUntil will error the parent observable if the notifier observable errors.
const source = interval(1000);
// added switchMap to throwError
const notifier = timer(2500).pipe(switchMap(() => throwError('error!')));
source.pipe(takeUntil(notifier)).subscribe({
next: (data) => console.log(data),
error: (err) => console.log(err)
});
This outputs:
0
1
error!

RxJS Throw error via NodeEventHandler in fromEventPattern

If I am using fromEventPattern, and the custom API has a separate handler for errors, how can I throw them into the stream via the handler function (NodeEventHandler)?
import { fromEventPattern } from 'rxjs';
const token = someAPI.registerEventHandler(function(event) {}, function(error) {}); // API takes a second function for errors.
someAPI.unregisterEventHandler(token);
const someAPIObservable = fromEventPattern(
function(handler) { return someAPI.registerEventHandler(handler, handler); }, // What should be the second argument here, in order to throw the error to any subscribers
function(handler, token) { someAPI.unregisterEventHandler(token); }
);
I could call the handler with the error (as above) and then pipe the resulting observable returned from fromEventPattern in order to check the type but it seems a bit verbose:
pipe(
map((x: unknown) => {
if (x instanceof Error) throw x;
return x;
}),
subject (which I am trying to replace with fromEventPattern) has a specific .error() method. Which would avoid all of the manual piping and type checking.
try this wrapper out
const yourEventObservable=new Observable(obs=>{
const token=someAPI.registerEventHandler(res=>{
if (res instanceof Error)
obs.error(x);
obs.next(res)
})
return ()=>someAPI.unregisterEventHandler(token);
}).pipe(share())

Javascript/typescript promise returns two types?

So, im running this code:
this.db.getDocumentClient()
.then(client => client.query(params).promise())
.then(data => { this.items = data.Items; })
.catch(err => logger.debug('error in refresh tasks', err))
.then(() => { this.refresher && this.refresher.complete() });
and getting this error:
typescript: D:/Developer/scrum/myApp123/src/pages/tasks/tasks.ts, line: 51
Property 'query' does not exist on type 'void | DocumentClient'. Property 'query' does not exist on type
'void'.
What in the world is type 'void | DocumentClient'? getDocumentClient looks like this:
getDocumentClient() {
return Auth.currentCredentials()
.then(credentials => new AWS.DynamoDB.DocumentClient({ credentials: credentials }))
.catch(err => logger.debug('error getting document client', err));
}
Promise<void | DocumentClient> is the return type of your getDocumentClient() function. The problem is that in .catch you do not re-throw the error and the function resolves to Promise<void>. To fix it, change your method to:
getDocumentClient() {
return Auth.currentCredentials()
.then(credentials => new AWS.DynamoDB.DocumentClient({ credentials: credentials }))
.catch(err => { logger.debug('error getting document client', err); throw err; });
}
This will cause the promise in your main code to fail and enters to the catch part, instead of resolving to void and then getting the runtime error.

Manually throw error ionic 2

I am communicating with a webservice and the return can be negative or porisitvo and will fall into the success of the call, but if the return is negative I need to manually throw an exception
.map(res => res.json())
.subscribe(res => {
let returno = JSON.parse(res.d);
if (returno.status == 'success') {
this._loggedIn(returno);
} else {
throw returno;
}
}, err => {
console.error('ERROR', err);
});
You can throw exceptions in JS by just passing objects to throw. So throw err in your case.
I expect you'll want all of your subscribers to handle the error in the same way? Therefore, you can handle the error at the Observable level, not the Subscriber level.
Thus, you can do something like the following:
public tryLogin(url: string): Observable<any> {
return this.http.get(url)
.map(res => res.json().d)
.map(res => {
if (res.status !== 'success') {
Observable.throw(res);
}
return res;
});
}
Then you can call this code in the following fashion:
this.tryLogin('mydata')
.subscribe(
data => this._loggedIn(data),
err => console.log(err);
)
The great thing with this approach is, if you don't want your subscribers to know what's gone on, you can abstract that and either authenticate them in the next callback, or handle the event of a failure in the error callback.

Categories

Resources