等待函数结束后再开始下一个函数

4

我正在使用 Angular 开发 Ionic v4 项目。

在我的项目中,我使用 BLE 与树莓派通信。

我需要完成以下几个步骤:

  1. 搜索设备
  2. 连接设备
  3. 启用通知
  4. 发送消息

目前我的实现大致如下:

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

我想做类似这样的事情:

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

问题: 我的函数 'myConnect' 在等待 'myScan' 结束后才开始执行。 因此,一些 'myConnect' 需要的东西在 'myScan' 中完成。 我已经尝试使用 'async/await' 但没有起作用。 我认为我没有正确使用它:
 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));
               });
           });
       });
   });

帮我理解如何创建一个函数,它可以等待前一个结束后再开始 :D


你最后的代码块看起来完全奇怪(并且可以简化为我在答案中发布的内容),但实际上它甚至应该做你想要的事情。因此,我认为你实际的问题在于myXXX函数的实现。你可能没有返回“正确”的承诺。你能展示一个不起作用的完整示例吗? - hansmaad
6个回答

5

只需使用async/await或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));

2

关键字await使JavaScript等待直到promise解决并返回其结果。

因此,您不需要在await this.myConnect().then(()=>{});中使用then

请使用await this.myConnect();

以下是示例,可帮助您更好地理解

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

我有这段代码:https://pastebin.com/VGSfJhqn 为什么我的bleconnect被拒绝了?在我的控制台中,我看到了“BLE:reject”。 - Amaury Laroze

0

这实际上就是 Promise 的用途。

Promise 是一个表示异步操作的最终完成或失败的对象。

你可以在这里了解有关 Promises 的更多信息。一旦你阅读完毕,我在下面为你留下了一个示例,以演示如何使用 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
你已经非常接近了!与其同时使用.thenasync,不如只使用其中之一。以下是几种实现你想要做的事情的方法:

使用.then

这是你典型的链接语法。Promises可以使用.then()进行链接,并传递一个函数。如果返回值是一个值(而不是Promise),那么它将解析为该值。但如果它确实返回了一个Promise,那么它将链接在一起,你的下一个.then()将解析为“内部”异步调用结果。

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

这种方法可以实现相同的结果,但使用特殊关键字自动链接承诺。 async/await 允许您跳过 .then()return 调用,因此您可以像调用同步函数一样调用异步函数。

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

了解有关Promise和Async JavaScript的更多信息,请查阅以下资源:


0

试试这个:

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

我会采用可观察对象。看看你想要什么...

  1. 搜索周围的设备
  2. 连接到此设备
  3. 激活通知
  4. 发送消息

1和2将与switchMap链接,因为响应彼此依赖。然后3和4可以按顺序执行,但彼此无关,因此我们可以使用concat来处理这些内容。(如果这个流程不正确,请根据这两个操作符进行相应调整)。

因此,我建议如下:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接