Reputation: 217
I'm working on Ionic v4 with Angular.
In my project i use the BLE to communicate with a raspberry.
I have several step :
Currently i have something like :
this.ble.scan().subscribe(result => {
if (device === theDeviceIWant) {
this.ble.connect(device.id).subscribe(result => {
this.ble.startNotification(infosaboutDevice).subscribe(result => {
// Message 1
this.ble.writeWithoutResponse(infos, message).then(result => {
// Message 2
this.ble.writeWithoutResponse(infos, message).then(result => {
// Message 3
this.ble.writeWithoutResponse(infos, message).then(result => {
// Message X
this.ble.writeWithoutResponse(infos, message).then(result => {
})
})
})
})
})
})
})
}
I want to do something like that :
this.myScan();
this.myConnect();
this.myNotification();
this.myMessage('Text 1');
this.myMessage('Text 2');
this.myMessage('Text X');
The probleme : My function ‘myConnect‘ don't wait the end of ‘myScan‘ to start. So somme stuff needed by ‘myConnect‘ is do in ‘myScan‘.
I already try to use ‘async/await‘ but does not work. I think i don't use it correctly :
await this.myConnect().then(async () => {
await this.myNotification().then(async () => {
await this.myMessage('03020000').then(async () => {
await this.myMessage('010100').then(async () => {
await this.myMessage('020200' + this.random.toString(16));
});
});
});
});
Help me to understand how to create a function who wait the end of the before one to start :D
Upvotes: 4
Views: 1288
Reputation: 2444
You're so close! Rather than using .then
and async
just use one or the other. Here are a few ways to accomplish what you are trying to do:
.then
:This is your typical chaining syntax. Promises can be chained using .then()
and passing in a function. If the return value is a value (not a Promise
) then it will resolve to that value. But if it did return a Promise
then it will chain together and your next .then()
will resolve to the "inner" async call result.
// Message 1
return this.ble.writeWithoutResponse(infos, message).then(result1 => {
// Message 2
return this.ble.writeWithoutResponse(infos, message);
}).then(result2 => {
// Message 3
return this.ble.writeWithoutResponse(infos, message);
)}.then(result3 => {
// Message X
return this.ble.writeWithoutResponse(infos, message);
}).then(result4 => { })
async
/await
This approach achieves the same result but uses special keywords to automatically chain promises together. async
/await
allows you to skip the .then()
and return
calls so you can invoke your async functions as if they were synchronous.
// Message 1
let result1 = await this.ble.writeWithoutResponse(infos, message)
// Message 2
let result2 = await this.ble.writeWithoutResponse(infos, message);
// Message 3
let result3 = await this.ble.writeWithoutResponse(infos, message);
// Message X
let result4 = await this.ble.writeWithoutResponse(infos, message);
To learn more about Promise
's and async javascript, check out these resources:
Upvotes: 0
Reputation: 73357
I would embrace Observables. Looking at what you want..
1 and 2 would be chained with switchMap
, as responses depend on each other. Then 3 and 4 could be performed in order, but not dependent on each other, therefore we could use concat
with those. (If this is not correct flow, adjust accordingly with these two operators).
So I suggest the following:
import { never } from 'rxjs';
import { switchMap, concat } from 'rxjs/operators';
// ...
this.ble.scan().pipe(
switchMap((device) => {
if (device === theDeviceIWant) {
return this.ble.connect(device.id)
}
// terminates rest of code
return never();
}),
concat(
this.ble.startNotification(...),
this.ble.writeWithoutResponse(...)
)
).subscribe(data => console.log(data))
Upvotes: 0
Reputation: 5941
This is essentially what Promises are made for.
A Promise is an object representing the eventual completion or failure of an asynchronous operation.
You can read up about Promises here. Once you read thru that, I left an example for you below to demonstrate how to use a Promise
:
//Wrap the operation you want to wait for in a Promise (in this case: setTimeout)
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('3 seconds have passed');
}, 3000);
});
//Once the operation is resolved the callback in the .then will be called
promise.then(val => document.querySelector('#target').innerHTML = val);
<div id="target">This message will change once the operation is resolved in 3 seconds.</div>
Upvotes: 0
Reputation: 3386
The keyword await makes JavaScript wait until that promise settles and returns its result.
So you dont need to use then
in await this.myConnect().then(()=>{});
use await this.myConnect()
;
Below is example which help you understand better
function SignalOne() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('Hello iam signal one');
}, 2000);
});
}
function SignalTwo() {
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('Hello iam signal Two');
}, 1000);
});
}
async function sendSignal() {
let one = await SignalOne();
let two = await SignalTwo();
console.log(one);
console.log(two);
}
sendSignal();
Upvotes: 2
Reputation: 126
Try this:
async myScan() {
// do things
}
ngOnInit() {
const scan = this.myScan(); // myScan doesn't actually have to return here
await scan;
const connect = this.myConnect();
await connect;
// more stuff
}
Upvotes: 0
Reputation: 18905
Just use async/await OR then
await this.myConnect(); // this awaits the Promise returned by myConnect to be resolved
await this.myNotification(); // same for this Promise
await this.myMessage('03020000'); // and so on...
await this.myMessage('010100');
await this.myMessage('020200' + this.random.toString(16));
Upvotes: 5