Узел запускает функции Syn c, ожидая внешнего значения перед возвратом. Асинхронный / ждать - PullRequest
0 голосов
/ 14 июля 2020

Я разрабатываю приложение Angular / Node, в этой части я запускаю внешнее устройство для чтения карты NF C и отправляю эту информацию на angular. Но узел возвращает HTTP-ответ, прежде чем я получу информацию NF C.

отредактируйте, чтобы уточнить некоторые моменты

key.controller. js Вот где я попадаю в node.js после того, как пользователь нажимает какую-то кнопку, запрашивая NF C Reader, чтобы прочитать некоторую карту

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 В этом помощнике есть дополнительный код, структурирующий телеграмму, отправляемую в считыватель NF C для чтения карты NF C

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


  }

Ожидается, что телеграмма будет отправляться считывателю NF C до что-то допустимое прочитано

 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 в режим чтения и начал прослушивать телеграммы, отправленные считывателем NF C, и фильтровать действительные телеграммы ответа.

    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 голосов
/ 14 июля 2020

В requestKeyCode() вам нужно либо вернуть обещание, созданное в их, либо await it. Как бы то ни было, ничего не было связано с обещанием, что функция asyn c возвращалась, поэтому она разрешится до того, как ваш 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, связано с асинхронными операциями внутри вашей функции. Этого не происходит в 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 возвращает, и возвращает обещание, которое разрешается в значение hasRead и работает рекурсивно.

Кроме того, в waitResponse нет ничего асинхронного, поэтому это может быть обычная функция, а не функция async.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...