如何在函数内部更新全局变量?Binance异步回调赋值后外部取值为空
核心原因:同步执行与异步回调的执行时序差异
首先拆解你能正常运行的同步示例执行逻辑:
- 先执行
var a = 10,将a赋值为10 - 接着执行
myFunction(),这个函数是同步立即执行的,函数运行完毕时就已经把a修改为20 - 最后才执行
console.log读取a的值,此时a已经完成修改,所以能正确输出20
而你调用binance.prices时无法拿到更新值,本质是这个接口是发起网络请求的异步非阻塞接口,执行流程完全不遵循同步代码的逐行顺序:
- 先执行
var priceNow = "",给priceNow赋初始空值 - 调用
binance.prices时,程序不会停下来等网络请求返回结果,而是直接把请求挂到后台队列,立刻继续向下执行后续代码 - 程序马上就运行到紧跟其后的
console.log(priceNow),这时候传入的回调函数根本还没执行——毕竟网络请求还没拿到响应,回调里给priceNow赋值的逻辑自然还没运行 - 等网络请求真的拿到数据、要执行回调给priceNow赋值的时候,你那行console.log早就执行完输出完毕了,所以看到的永远是空值,拿不到更新后的结果。
常用解决方案
方案1:将依赖priceNow的逻辑全部移入回调函数
这是最适配原生回调写法的方式,等回调拿到并完成priceNow赋值后,再执行所有依赖这个值的逻辑:
var priceNow = "" binance.prices('BNBBTC', (error, ticker) => { // 优先处理异常分支 if (error) { console.error("获取行情失败:", error) return } // 拿到返回值后完成变量赋值 priceNow = ticker.BNBBTC; // 所有需要用到priceNow的业务逻辑,全部写在这个位置 console.log("当前BNBBTC价格:", priceNow) })
方案2:用Promise+async/await封装成同步风格写法
如果不想写嵌套回调导致逻辑绕,可以把原生回调形式的接口封装成可等待的Promise对象,用async/await语法实现接近同步代码的执行逻辑,流程就和你最开始的同步示例完全一致:
// 封装行情获取接口为Promise function fetchBnbBtcPrice() { return new Promise((resolve, reject) => { binance.prices('BNBBTC', (error, ticker) => { if (error) return reject(error) resolve(ticker.BNBBTC) }) }) } // 用async函数按顺序执行业务逻辑 async function runBusinessLogic() { try { // 这一行会等待异步请求完成,拿到priceNow之后再向下执行 const priceNow = await fetchBnbBtcPrice() // 后续所有依赖priceNow的逻辑,直接顺序编写即可 console.log("当前BNBBTC价格:", priceNow) } catch (err) { console.error("获取行情异常:", err) } } runBusinessLogic()
注意:不要用死循环阻塞主线程等待priceNow更新,比如写
while(priceNow === "") {}这类代码——这种写法会把JS主线程完全堵死,异步回调根本没有执行机会,永远等不到值更新。
内容的提问来源于stack exchange,提问作者Jabibi
相关产品推荐
相关产品推荐

