异步等待和非异步函数问题

时间:2018-02-05 16:57:42

标签: javascript typescript asynchronous async-await

我正在尝试处理使用异步函数的库并且有点迷失。我想调用一个函数来返回一个字符串,但我被绊倒了。这是我到目前为止所拥有的。 ZeroEx库函数似乎都使用async / await所以我的理解是我只能从另一个异步方法调用它们。但这不会导致连锁反应意味着每个方法都需要异步吗?或者我错过了什么?

function main() {
    var broker = zmq.socket('router');
    broker.bindSync('tcp://*:5671');


    broker.on('message', function () {
    var args = Array.apply(null, arguments)
        , identity = args[0]
        , message = args[1].toString('utf8');

        if(message === 'TopOfBook') {
            broker.send([identity, '', getTopOfBook()]);
        }

        //broker.send([identity, '', 'TEST']);
        //console.log('test sent');
    })
}

async function getTopOfBook() {
    var result: string = 'test getTopOfBook';
    const EXCHANGE_ADDRESS = await zeroEx.exchange.getContractAddress();
    const wethTokenInfo = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync('WETH');
    const zrxTokenInfo = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync('ZRX');

    if (wethTokenInfo === undefined || zrxTokenInfo === undefined) {
        throw new Error('could not find token info');
    }

    const WETH_ADDRESS = wethTokenInfo.address;
    const ZRX_ADDRESS = zrxTokenInfo.address;


    return result;
}

main();

函数getTopOfBook()没有将任何内容返回给main()函数,因此代理永远不会发送结果。带有'TEST'的注释掉的broker.send()工作正常。谢谢你的期待。

编辑: 我试图使主方法异步,所以我可以使用await但它给出一个错误,我只能在异步函数中使用await。 broker.on()调用可以导致这个吗?

  const main = async () => {
      try{
      var broker = zmq.socket('router');
      broker.bindSync('tcp://*:5671');


      broker.on('message', function () {
      var args = Array.apply(null, arguments)
          , identity = args[0]
          , message = args[1].toString('utf8');

          console.log(message);
          if(message === 'TopOfBook') {
>>            var test = await getTopOfBook();
              console.log('in top of book test');

              broker.send([identity, '', test]);
          }

          //broker.send([identity, '', 'TEST']);
          //console.log('test sent');
      })
      } catch (err) {
          console.log(err);
      }
  }

编辑2: 我当前的工作代码,感谢所有有建议/解决方案的人!我显然必须填写getTopOfBook()函数来返回实际结果。如果您有更多建议,请按我的方式发送。我正在尝试构建一个后端,它将从geth rpc获取数据并将其发送到C#GUI前端。

var main = function() {
    try{
    var broker = zmq.socket('router');
    broker.bindSync('tcp://*:5672');

    broker.on('message', function () {
    var args = Array.apply(null, arguments)
        , identity = args[0]
        , message = args[1].toString('utf8');

        if(message === 'TopOfBook') {
            getTopOfBook().then((result) => {
                broker.send([identity, '', result])
            });
        }
    })
    } catch (err) {
        console.log(err);
    }
}

async function getTopOfBook() {
    var result: string = 'test getTopOfBook';
    const EXCHANGE_ADDRESS = await zeroEx.exchange.getContractAddress();
    const wethTokenInfo = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync('WETH');
    const zrxTokenInfo = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync('ZRX');

    if (wethTokenInfo === undefined || zrxTokenInfo === undefined) {
        throw new Error('could not find token info');
    }

    const WETH_ADDRESS = wethTokenInfo.address;
    const ZRX_ADDRESS = zrxTokenInfo.address;


    return result;
}

main();

3 个答案:

答案 0 :(得分:0)

您错过了异步函数只是编写代码的方法。实际执行的每个异步函数都会生成一个promise。这就是为什么你可以await任何承诺,你可以与任何使用异步的库进行交互,而无需自己使用异步函数。

当你调用异步函数时,它应该返回一个promise(在异步函数上自动发生)。承诺只不过是一个then方法的对象。这种方法接受回调,您可以在其中处理剩余的逻辑。

function main() {
    var broker = zmq.socket('router');
    broker.bindSync('tcp://*:5671');


    broker.on('message', function () {
    var args = Array.apply(null, arguments)
        , identity = args[0]
        , message = args[1].toString('utf8');

        if(message === 'TopOfBook') {
            return getTopOfBook().then( result => 
                broker.send([identity, '', result])
            ) // If the broker also returns a promise, you can continue the flow here
            .then(()=> console.log('test sent'))
        }
    })
}

就我个人而言,我根本不喜欢异步等待因为涉及太多魔法而让人们忘记了承诺和异步代码的实际性质。

此外,在处理promises时,您应该始终记得返回任何可以调用/生成的承诺,以便外部代码可以继续链并处理错误消息。

答案 1 :(得分:0)

您的函数getTopOfBook会返回Promise,因此您需要使用函数then

按以下方式调用该功能:

getTopOfBook().then((result) => {
  console.log("Result:" + result);
});

请查看此代码段



let sleep = (fn) => {
  setTimeout(fn, 1000);
};

let getContractAddress = function(cb) {
  return new Promise((r) => sleep(() => {
    r('getContractAddress')
  }));
};

let getTokenBySymbolIfExistsAsync = function(str) {
  return new Promise((r) => sleep(() => {
    r({
      address: 'getTokenBySymbolIfExistsAsync: ' + str
    })
  }));
};

let WETH_ADDRESS = '';
let ZRX_ADDRESS = '';
let EXCHANGE_ADDRESS = '';

async function getTopOfBook() {
  var result = 'test getTopOfBook';

  const EXCHANGE_ADDRESS = await getContractAddress();
  const wethTokenInfo = await getTokenBySymbolIfExistsAsync('WETH');
  const zrxTokenInfo = await getTokenBySymbolIfExistsAsync('ZRX');

  if (wethTokenInfo === undefined || zrxTokenInfo === undefined) {
    return Promise.reject(new Error('could not find token info'));
  }

  const WETH_ADDRESS = wethTokenInfo.address;
  const ZRX_ADDRESS = zrxTokenInfo.address;

  console.log(WETH_ADDRESS);
  console.log(ZRX_ADDRESS);
  console.log(EXCHANGE_ADDRESS);

  return result;
}

var main = function() {
  console.log('Waiting response...');
  getTopOfBook().then((result) => {
    console.log("Result:" + result);
    console.log('DONE!');
  }).catch((error) => {
      console.log(error);
  });      
};

main();

.as-console-wrapper {
  max-height: 100% !important
}




如果要抛出错误,请使用函数Promise.reject()

  • 在此调用的同时,您需要传递reject函数或调用catch函数。

在此示例中,我们通过reject功能:

(error) => {
    console.log(error); 
}

如果您未通过reject函数,则需要调用catch函数以处理抛出的错误。



let sleep = (fn) => {
  setTimeout(fn, 1000);
};

let getContractAddress = function(cb) {
  return new Promise((r) => sleep(() => {
    r('getContractAddress')
  }));
};

let getTokenBySymbolIfExistsAsync = function(str) {
  return new Promise((r) => sleep(() => {
    r()
  }));
};

let WETH_ADDRESS = '';
let ZRX_ADDRESS = '';
let EXCHANGE_ADDRESS = '';

async function getTopOfBook() {
  var result = 'test getTopOfBook';

  const EXCHANGE_ADDRESS = await getContractAddress();
  const wethTokenInfo = await getTokenBySymbolIfExistsAsync('WETH');
  const zrxTokenInfo = await getTokenBySymbolIfExistsAsync('ZRX');

  if (wethTokenInfo === undefined || zrxTokenInfo === undefined) {
    return Promise.reject('Could not find token info');
  }

  const WETH_ADDRESS = wethTokenInfo.address;
  const ZRX_ADDRESS = zrxTokenInfo.address;

  console.log(WETH_ADDRESS);
  console.log(ZRX_ADDRESS);
  console.log(EXCHANGE_ADDRESS);

  return result;
}

var main = function() {
  console.log('Waiting response...');
  getTopOfBook().then((result) => {
    console.log("Result:" + result);
    console.log('DONE!');
  }, (error) => {
    console.log(error); 
  }).catch((error) => {
    console.log(error); // This line will be called if reject function is missing.
  });

};

main();

.as-console-wrapper {
  max-height: 100% !important
}




资源

  

当调用异步函数时,它返回一个Promise。当异步函数返回一个值时,将使用返回的值解析Promise。当异步函数抛出异常或某个值时,将使用抛出的值拒绝Promise。

答案 2 :(得分:0)

回调函数需要是异步

broker.on('message', async function () {
    var args = Array.apply(null, arguments)
        , identity = args[0]
        , message = args[1].toString('utf8');

        if(message === 'TopOfBook') {
            var test = await getTopOfBook();
            broker.send([identity, '', test]);
        }

        //broker.send([identity, '', 'TEST']);
        //console.log('test sent');
    })