Issue
Having spent some time trying to get my head around using observable's on service functions, I have decided to ask the question on here.
I have a service which is designed around WebUSB in order to make a connection to a device attached to the computer within the browser. The code works but it needs to be better, in that when it calls the function to connect, since it is a pure function, the code continues in the background within the controller regardless of whether or not a device is actually selected.
webSerialService.ts
// Grab and assign a port to the variables this.device.
requestPorts() {
navigator.serial.requestPort(this.filters)
.then(
(result) => {
this.device = result;
// Open up the port.
this.device.open({ baudRate: 9600 });
},
(error) => {
console.log("The user selected the cancel, no port was selected.");
}
);
return this.device;
}
And the receiving controller code:
public connect() {
// Let the user know they are about to do something.
this.displayText = "-----";
try {
// Return the device selected.
this.device = this.webSerialService.requestPorts();
} catch (e) {
console.log(e);
}
// Have we selected a port or not?
if (this.webSerialService.device == false) {
// Let the user know that no port was selected.
this.displayText = "NO PORT";
}
else {
// Let the user know they are connected.
this.displayText = "Awaiting Data";
}
}
The second part of the controller code, obviously executes without waiting for a device to be selected, which is not what I want, but expected. Having tried to turn the service function into an observable and then subscribing to it within the controller, I would get the error message when the "connect" function is fired:
TypeError: Cannot read properties of undefined (reading 'subscribe')
I amended the function definition within the server to:
requestPorts(): Observable<any> {
And then the controller code would be:
this.webSerialService.requestPorts().subscribe(data => {console.log(data)});
Which is where the aforementioned error would occur.
I've tried several various examples found on the internet and on StackOverflow, but I seem to be missing a crucial bit of understanding how Observables work and how to define them for functions.
Thank-you for any input and insight you can provide.
Solution
The problem is not in the Observable itself. The problem is that the moment you return this.device, it hasn't been assigned a value yet. It's undefined. Hence the error.
Try converting the Promise into an Observable like this instead:
import { from, map } from 'rxjs';
// ...
requestPorts(): Observable<any> {
return from(navigator.serial.requestPort(this.filters)).pipe(
map((result) => {
this.device = result;
this.device.open({ baudRate: 9600 });
return this.device;
})
);
}
Answered By - Vasileios Kagklis
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.