Meteor中WebSocket存JSON到MongoDB遇“Can't wait without a fiber”错误求助
我太懂这个坑了!你遇到的这个错误,本质是Meteor的MongoDB操作依赖Fiber上下文,但币安WebSocket的回调是运行在原生Node.js的异步事件循环里,不在Meteor的Fiber环境中,所以同步的MongoDB查询(比如count()、find())就会抛出这个“没法在没有fiber的情况下等待”的错误。
给你两个最实用的解决办法,优先用第一个:
1. 用Meteor.bindEnvironment包裹回调函数
这是Meteor官方推荐的处理第三方异步回调的方式,它能把你的回调函数“包裹”进Meteor的Fiber上下文里,让MongoDB操作能正常获取到所需的环境。
修改你的代码如下:
binance.websockets.miniTicker(Meteor.bindEnvironment((markets) => { // 获取币安实时数据 if (db.Coins.find({}).count() === 0) { // 若数据库当前无数据 markets.forEach(Meteor.bindEnvironment((coin) => { // 这里写你遍历每个币种的处理逻辑,比如插入数据 // 示例:db.Coins.insert({ symbol: coin.symbol, price: coin.lastPrice }); })); } }));
注意:不仅外层的WebSocket回调要包,内层的forEach回调也需要用Meteor.bindEnvironment包裹,因为forEach的回调同样是异步执行的,也会脱离Fiber上下文。
2. 改用异步MongoDB操作(备选方案)
如果你不想用Fiber,也可以直接调用MongoDB的异步API(比如countDocuments()代替同步的count()),不过这种方式在Meteor里不如第一种常用,因为Meteor的生态更适配Fiber模式。示例大概是这样:
binance.websockets.miniTicker(async (markets) => { const count = await db.Coins.find({}).countDocuments(); if (count === 0) { for (const coin of markets) { await db.Coins.insertOne(coin); } } });
但要注意,这种方式需要确保你的MongoDB驱动是支持异步操作的版本,而且在Meteor里使用原生异步API可能会有其他上下文问题,所以还是优先第一种方案。
额外提醒
不止是WebSocket回调,所有第三方库的异步回调(比如HTTP请求、定时器)只要涉及到Meteor的MongoDB操作,都需要用Meteor.bindEnvironment包裹,不然都会碰到类似的Fiber错误。
内容的提问来源于stack exchange,提问作者RufusWhite

