如何在Deno中读取WebSocket返回的Blob数据?
问题描述
我正在尝试在Deno中通过WebSocket读取AISstream的数据,相关代码如下(需使用AISstream提供的API密钥才能运行):
/** * URL used by the API; this might change if the version changes or at any time, since it's experimental */ const AIS_API_URL = "wss://stream.aisstream.io/v0/stream"; export const defaultBoundingBox = [ [ [-90, -180], [90, 180], ], ]; let socket = null; // Creates a deno websocket client and subscribes to the AIS API export function createSocket(apiKey, boundingBoxes = defaultBoundingBox) { if (socket) { return socket; } socket = new WebSocket(AIS_API_URL); socket.onopen = () => { console.log("Socket connected"); socket.send( JSON.stringify({ apiKey, boundingBoxes, }) ); }; socket.onmessage = (event) => { const reader = new FileReader(); console.log(event); const decodedBlob = reader.readAsText(event.data); console.log(decodedBlob); }; socket.onclose = () => { console.log("Socket closed"); }; return socket; }
问题出在onmessage回调中:消息已成功接收,但event.data是Blob类型。我尝试用TextDecoder和readAsText解码,结果都返回undefined。在普通JavaScript中,event.data是字符串,可直接解析为JSON,但我无法解决Deno中的这个问题。
解决方案
Deno中WebSocket返回的Blob无法同步读取内容,FileReader.readAsText是异步操作,会立即返回undefined,必须通过异步方式获取结果。以下是两种可行的解决方法:
方法一:使用Blob自带的text()方法(推荐)
Blob实例的text()方法返回Promise,配合async/await可直接获取文本内容,代码更简洁:
socket.onmessage = async (event) => { if (event.data instanceof Blob) { const text = await event.data.text(); const aisData = JSON.parse(text); console.log(aisData); } };
方法二:监听FileReader的load事件
如果坚持使用FileReader,需要通过监听load事件获取解码后的结果:
socket.onmessage = (event) => { const reader = new FileReader(); reader.onload = () => { const text = reader.result; const aisData = JSON.parse(text); console.log(aisData); }; reader.readAsText(event.data); };
完整修正后的代码
/** * URL used by the API; this might change if the version changes or at any time, since it's experimental */ const AIS_API_URL = "wss://stream.aisstream.io/v0/stream"; export const defaultBoundingBox = [ [ [-90, -180], [90, 180], ], ]; let socket = null; // Creates a deno websocket client and subscribes to the AIS API export function createSocket(apiKey, boundingBoxes = defaultBoundingBox) { if (socket) { return socket; } socket = new WebSocket(AIS_API_URL); socket.onopen = () => { console.log("Socket connected"); socket.send( JSON.stringify({ apiKey, boundingBoxes, }) ); }; // 使用Blob.text()方法解码并解析数据 socket.onmessage = async (event) => { try { const text = await event.data.text(); const aisData = JSON.parse(text); console.log(aisData); } catch (err) { console.error("解码或解析数据失败:", err); } }; socket.onclose = () => { console.log("Socket closed"); socket = null; // 关闭后重置socket,允许重新创建连接 }; socket.onerror = (err) => { console.error("Socket错误:", err); }; return socket; }
内容的提问来源于stack exchange,提问作者jjmerelo
相关产品推荐
相关产品推荐

