【问题标题】:Node run functions Sync, waiting an external value before returning . Async/wait节点运行函数同步,在返回之前等待一个外部值。异步/等待
【发布时间】:2020-07-15 08:40:02
【问题描述】:

我在这部分开发一个 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 请求。

如何强制它等待。

【问题讨论】:

  • 尝试使用Promise.all()

标签: node.js promise async-await


【解决方案1】:

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 的承诺,因此没有理由使用同样解析为 keyCode.then() 做出另一个承诺。


那么sendTelegramLoop()也有问题。您需要确保 async 函数返回的承诺与函数内部的异步操作相关联。 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 函数。

【讨论】:

  • 首先,感谢您花时间帮助我!延迟(50)是向 NFC 阅读器发送新电报以尝试新读取的超时。这是必要的,以确保系统将尝试读取卡。如果 15 秒后没有读取任何内容,稍后将实现超时以跳过此操作。关于 hasRead,它带有 keyCode,当我开始它是为了找出我们应该何时停止这个循环完成 waitResponse 是我分解 NFC 读取器响应的地方,以确保它是有效的。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2021-10-22
  • 2014-11-26
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多