Node.js异步场景下如何让if语句在binancePrice、coinbasePrice调用后执行
问题原因
你的代码问题本质是JavaScript异步执行逻辑:request 属于异步IO操作,调用binancePrice()和coinbasePrice()后,主线程不会等待请求返回,会直接往下执行价格判断的代码,此时两个接口的返回数据还没赋值,自然会报变量未定义的错误。
另外你用全局变量存储接口返回数据的写法有很大隐患,当多个用户同时请求接口时,全局变量会被不同请求的返回值覆盖,出现数据错乱。
可行方案
我们可以把回调形式的请求改造成返回Promise的形式,再用async/await+Promise.all并行请求两个接口,等两个请求都完成后再执行后续逻辑:
第一步:改写价格查询函数,返回Promise
// 请求币安BTC价格 function binancePrice() { return new Promise((resolve, reject) => { request(binanceAPI, (error, response, body) => { // 先处理请求报错的情况 if (error) return reject(error) const binanceData = JSON.parse(body); if (!binanceData) { return reject(new Error('币安接口返回空数据')) } console.log(`币安最近${binanceData.mins}分钟的BTC价格为 ${binanceData.price}`); // 返回解析后的数据 resolve(binanceData) }) }) } // 请求coinbase BTC价格 function coinbasePrice() { return new Promise((resolve, reject) => { request(coinbaseAPI, (error, resp, body) => { if (error) return reject(error) const coinbaseData = JSON.parse(body); if (!coinbaseData || !coinbaseData.data) { return reject(new Error('Coinbase接口返回数据异常')) } console.log(`Coinbase的BTC价格为 ${coinbaseData.data.amount} ${coinbaseData.data.currency}`); resolve(coinbaseData) }) }) }
第二步:改写路由逻辑,等待两个请求完成后再执行判断
注意要给路由的处理函数加上async标记,同时添加异常捕获逻辑处理接口请求失败的情况:
// Router testPay.route('/exchange-routing') .get(async (req, res) => { try { const cryptoAmount = parseFloat(req.query.amount, 10); let exchange = ''; let price = 0; console.log(`用户选择的BTC数量为 ${cryptoAmount}`); if (cryptoAmount > 0) { // 并行发起两个请求,等两个都返回结果后再往下执行 const [binanceData, coinbaseData] = await Promise.all([ binancePrice(), coinbasePrice() ]) const binancePriceVal = parseFloat(binanceData.price, 10) const coinbasePriceVal = parseFloat(coinbaseData.data.amount, 10) // 现在两个数据都已拿到,可以正常比较 if (binancePriceVal > coinbasePriceVal) { exchange = 'Coinbase'; price = coinbasePriceVal; } else { exchange = 'Binance'; price = binancePriceVal; } // 返回结果给客户端 const answer = { btcAmount: cryptoAmount, usdAmount: cryptoAmount * price, exchange, }; res.json(answer); } else { res.send('BTC数量必须大于0'); } } catch (err) { // 捕获所有异常,统一返回错误 console.error('请求出错:', err) res.status(404).json({msg: '获取价格失败,请稍后重试'}) } });
补充说明
- 你原来的代码里给Coinbase价格赋值时写的
parseFloat(coinbaseData.price, 10)是错误的,根据你之前的打印逻辑,Coinbase的价格存在coinbaseData.data.amount里,上面的代码已经做了修正 Promise.all会并行发起两个请求,比串行等待两个请求依次返回的效率更高- 所有请求的异常都统一在路由的try catch里处理,避免接口无响应
内容的提问来源于stack exchange,提问作者OliT
相关产品推荐
相关产品推荐

