节点运行功能Sync,在返回之前等待外部值。异步/等待

时间:2020-07-14 01:59:52

标签: node.js promise async-await

我将在本部分中开发Angular / Node应用程序,然后触发外部设备读取NFC卡,并将该​​信息发送给angular。但是,在我获得NFC信息之前,节点正在返回HTTP响应。

编辑以阐明更多要点

key.controller.js ,这是用户单击某个按钮请求NFC读取器读取某些卡之后,我在这里进入node.js的地方。

exports.requestKeyCode = async (req, res) => {
  console.log('KeyController');

  keyHelper.requestKeyCode().then( data =>{
    console.log('Did I wait?')
    res.send(data);
  }).catch(err => {
    res.status(500).send({
      message:
        err.message || "Some error occurred while retrieving Role."
    });
  });

    
  }

keyYHelper 在此帮助器中,有一些额外的代码构成了发送给NFC读取器以读取NFC卡的电报

 exports.requestKeyCode  = async function()  {
  
      console.log('Entered requestDeviceInfo')
      finalTelegram=newData.toString(16)+CHKS.toString(16);
      this.ft=finalTelegram;
  
      sendTelegramLoop(this.ft, 0).then( keyCode => {
        return  keyCode ;
      })


  }

在这里,希望一直将电报发送到NFC读取器,直到读取到有效的内容为止

 async function sendTelegramLoop(telgeram, i ) {
     
    setTimeout(() => {
        hasRead = false;
      
        global.comPort.write(telgeram, 'hex' ,function(err) {
          hasRead =  waitResponse().then(hasRead => {
            if (err) {
              return console.log('Error on write: ', err.message)
            }
            if (!hasRead){
              sendTelegramLoop(telgeram, i++);
            } else {
              console.log('enteredExitRoutine');
              return hasRead;
            } 
            } );                   
        }) 
    }, 50)
}

在这里我将comPort设置为读取模式,并开始侦听NFC阅读器发送的电报,并过滤有效的响应电报。

    async function waitResponse() {
      
    console.log("waiting keyInfo");
    rcvTelegram =  global.comPort.read().toString('hex');
     
    if (rcvTelegram.startsWith('a40101001c0a000') && rcvTelegram.length===56){
        console.log("breaking telegram")
        keyInfo =  telegramHelper.breakTelegram(rcvTelegram) ;
        console.log('Key Read='+ keyInfo);
        return keyInfo;
    } 
      

} 

基本上发生的是,在我将命令发送到设备以读取卡之后,nodeJS返回了HTTP请求。

我如何强迫它等待。

1 个答案:

答案 0 :(得分:0)

requestKeyCode()中,您需要返回在其中创建的承诺,或者返回await中的承诺。照原样,没有任何东西可以保证异步函数正在返回,因此它可以在您的sendTelegraphLoop()实际完成之前解决。

exports.requestKeyCode  = async function()  {
  
      console.log('Entered requestDeviceInfo')
      finalTelegram=newData.toString(16)+CHKS.toString(16);
      this.ft=finalTelegram;
  
      return sendTelegramLoop(this.ft, 0);
}

或使用await

exports.requestKeyCode  = async function()  {
  
      console.log('Entered requestDeviceInfo')
      finalTelegram=newData.toString(16)+CHKS.toString(16);
      this.ft=finalTelegram;
  
      let keyCode = await sendTelegramLoop(this.ft, 0);
      return keyCode;
}

此外,没有理由使用此内容:

 .then(keyCode => {
     return keyCode;
 });

,因为它没有任何用处。这只是多余的代码。您已经解决了keyCode的诺言,因此没有理由再用.then()做出也解决成keyCode的诺言。


然后sendTelegramLoop()也有问题。您需要确保async函数返回的Promise与函数内部的异步操作挂钩。 sendTelegramLoop()中没有发生这种情况。

这里是解决sendTelegramLoop()的问题:

function delay(t) {
    return new Promise(resolve => setTimeout(resolve, t));
}

global.comPost.writeP = util.Promisify(global.comPost.write);

async function sendTelegramLoop(telgeram, i ) {
    try {
        // is this delay a hack?  Why is it here
        await delay(50);
        hasRead = false;
        await global.comPort.writeP(telgeram, 'hex');
        hasRead = await waitResponse();
        if (!hasRead) {
            return sendTelegramLoop(telegeram, i++);
        } else {
            console.log('enteredExitRoutine');
            return hasRead;
        }
    } catch(err) {
        console.log('Error on write: ', err.message)
        throw err;          // propagate error back to caller
    }
}

使用未在本地声明的更高范围的变量(如hasRead)看起来很麻烦。无论如何,这个新的实现实际上将所有异步操作都挂接到async函数返回的promise中,并返回一个解析为hasRead值并可以递归工作的promise。


此外,waitResponse似乎没有异步的任何内容,因此它只能是常规函数,而不是async函数。