Pracuję nad Ionic v4 z Angular.

W moim projekcie używam BLE do komunikacji z maliną.

Mam kilka kroków:

  1. Wyszukaj urządzenie wokół mnie
  2. Połącz się z tym urządzeniem
  3. Aktywuj powiadomienie
  4. Wysłać wiadomości

Obecnie mam coś takiego:

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 => {
              })
            })
          })
        })
      })
    })
  })
}

Chcę zrobić coś takiego:

this.myScan();
this.myConnect();
this.myNotification();
this.myMessage('Text 1');
this.myMessage('Text 2');
this.myMessage('Text X');

Problem: Moja funkcja „myConnect” nie czeka na uruchomienie końca „myScan”. Tak więc niektóre rzeczy potrzebne „myConnect” są dostępne w „myScan”.

Próbuję już użyć „async / await”, ale nie działa. Myślę, że nie używam go poprawnie:

 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));
               });
           });
       });
   });

Pomóż mi zrozumieć, jak stworzyć funkcję, która czeka na koniec poprzedniej: D

4
Amaury Laroze 19 listopad 2019, 18:54
Twój ostatni blok kodu wygląda zupełnie dziwnie (i można go uprościć do tego, co zamieściłem w mojej odpowiedzi), ale powinien nawet robić to, co chcesz. Myślę więc, że twój rzeczywisty problem tkwi w implementacjach funkcji myXXX. Prawdopodobnie nie zwracasz tam „właściwej” obietnicy. Czy możesz pokazać pełny przykład, który nie działa?
 – 
hansmaad
20 listopad 2019, 10:27

6 odpowiedzi

Po prostu użyj async / await LUB 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));
5
hansmaad 19 listopad 2019, 19:01

Słowo kluczowe await sprawia, że JavaScript czeka, aż obietnica się spełni i zwróci wynik.

Nie musisz więc używać then i await this.myConnect().then(()=>{});

Użyj await this.myConnect();

Poniżej znajduje się przykład, który pomoże Ci lepiej zrozumieć

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();
2
Saurabh Yadav 19 listopad 2019, 19:07
Mam ten kod : pastebin.com/VGSfJhqn Dlaczego mój bleconnect jest odrzucany? W mojej konsoli zobaczyłem 'BLE: odrzuć'
 – 
Amaury Laroze
19 listopad 2019, 19:39

Spróbuj tego:

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
}
0
Josh Lind 19 listopad 2019, 19:06

To jest zasadniczo to, do czego są stworzone Promises.

Promise to obiekt reprezentujący ostateczne zakończenie lub niepowodzenie operacji asynchronicznej.

Tutaj możesz przeczytać o obietnicach. Kiedy już to przeczytasz, zostawiłem dla ciebie przykład poniżej, aby zademonstrować, jak używać 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>
0
Tom O. 19 listopad 2019, 19:15

Przyjąłbym Observables. Patrzę na to, czego chcesz ...

  1. Wyszukaj urządzenie wokół mnie
  2. Połącz się z tym urządzeniem
  3. Aktywuj powiadomienie
  4. Wysłać wiadomości

1 i 2 byłyby połączone z switchMap, ponieważ odpowiedzi zależą na siebie. Wtedy 3 i 4 mogłyby być wykonane w kolejności, ale nie zależne od siebie, dlatego moglibyśmy użyć concat z nimi. (Jeśli to nie jest prawidłowy przepływ, dostosuj odpowiednio za pomocą tych dwóch operatorów).

Sugeruję więc:

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))
0
AJT82 19 listopad 2019, 20:55

Jesteś tak blisko! Zamiast używać .then i async po prostu użyj jednego lub drugiego. Oto kilka sposobów na osiągnięcie tego, co próbujesz zrobić:

Korzystanie z .then:

To jest twoja typowa składnia tworzenia łańcuchów. Obietnice można łączyć za pomocą .then() i przekazując funkcję. Jeśli zwracana wartość jest wartością (nie Promise), to zostanie rozwiązana do tej wartości. Ale jeśli zwrócił Promise, zostanie połączony, a następne .then() przekształci się w „wewnętrzny” wynik wywołania asynchronicznego.

// 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 => {  })

Za pomocą async / await

Takie podejście pozwala osiągnąć ten sam wynik, ale wykorzystuje specjalne słowa kluczowe, aby automatycznie łączyć ze sobą obietnice. async/await pozwala pominąć wywołania .then() i return, dzięki czemu można wywołać funkcje asynchroniczne tak, jakby były synchroniczne.

// 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);

Aby dowiedzieć się więcej o Promise i async javascript, zapoznaj się z tymi zasobami:

0
Jim Buck 19 listopad 2019, 21:29