如何从内部函数向外部函数返回值?WebSocket场景下获取times平均值
问题核心原因
- 你当前代码存在两个核心错误:
- 空
while(times.length < 10){}会完全阻塞JS单线程的主线程,WebSocket的onmessage回调永远得不到执行机会,会直接进入死循环。 - WebSocket连接、消息收发都是异步操作,你无法用同步
return的方式直接拿到异步逻辑的结果,必须用异步方案处理。
- 空
- 额外逻辑缺陷:原代码用请求ID作为数组索引赋值,会导致
times.length完全不符合预期,无法正确判断是否收满10次响应。
解决方案
将函数改造为返回Promise,在所有消息接收完成后resolve计算得到的平均值即可,改造后代码如下:
// 如果你已经全局定义了Math.average可删除本段 Math.average = function(arr) { return arr.reduce((sum, val) => sum + val, 0) / arr.length; } function pingr(url) { // 用Promise封装异步逻辑 return new Promise((resolve, reject) => { const times = []; const sendTimes = {}; // 存储每个请求id的发送时间,确保延迟计算准确 const totalPacket = 10; let receivedPacket = 0; const pinger = new WebSocket(url || "wss://speedtest.yimmee.repl.co"); pinger.onmessage = (message) => { const res = JSON.parse(message.data); const delay = Date.now() - sendTimes[res.id]; times.push(delay); receivedPacket++; // 收满所有包后处理结果 if (receivedPacket === totalPacket) { pinger.close(); resolve(Math.average(times)); } }; pinger.onerror = (error) => { console.log(error); pinger.close(); reject(error); }; pinger.addEventListener("open", () => { // 批量发送请求,避免重复代码 for(let i=0; i<totalPacket; i++) { // 加随机数避免同毫秒发送导致ID重复 const id = Date.now() + Math.random(); sendTimes[id] = Date.now(); pinger.send(JSON.stringify({ id })); } }); }) }
调用方式
// 方式1:通过.then获取结果 pingr().then(avgDelay => { console.log("平均延迟为:", avgDelay); }).catch(err => { console.log("测速失败:", err); }); // 方式2:在async函数中通过await调用 async function testSpeed() { try { const avgDelay = await pingr(); console.log("平均延迟为:", avgDelay); } catch (err) { console.log("测速失败:", err); } } testSpeed();
内容的提问来源于stack exchange,提问作者TGP1cccul8r
相关产品推荐
相关产品推荐

