求助:使用try-catch无法处理ytdl-core模块的未处理Promise拒绝问题
解决ytdl-core未捕获的Promise拒绝问题
我来帮你分析下问题所在,以及对应的解决办法:
为什么你的try-catch没生效?
你用了try-catch,但没捕获到错误的核心原因是:ytdl()返回的是一个可读流,而内部的格式选择错误是在异步流程中抛出的Promise拒绝——你没有用await等待这个异步操作完成,而是直接调用了pipe()。try-catch只能捕获同步错误,以及async函数中被await的Promise的拒绝,所以这个异步错误就成了未处理的Promise拒绝。
解决方案1:监听流的error事件
ytdl返回的流会在内部发生错误时触发error事件,我们可以通过监听这个事件来捕获错误:
app.get("/getaudio", async (req, res) => { const videoID = req.query.v; const quality = req.query.q; try { const audioStream = ytdl("http://www.youtube.com/watch?v=" + videoID, { quality: quality, filter: "audioonly", }); // 监听流的错误事件,捕获内部Promise拒绝 audioStream.on('error', (error) => { if (!res.headersSent) { res.status(500).send("Encountered Error: " + error.message); } }); audioStream.pipe(res); } catch (e) { res.status(500).send("Encountered Error: " + e.message); } });
解决方案2:拆分异步步骤,用await捕获所有错误
这种方式更可控,我们先手动获取视频信息、选择格式,再创建流,这样所有错误都会被try-catch捕获:
app.get("/getaudio", async (req, res) => { const videoID = req.query.v; const quality = req.query.q; try { // 1. 先获取视频详细信息(异步操作,用await等待完成) const videoInfo = await ytdl.getInfo(`http://www.youtube.com/watch?v=${videoID}`); // 2. 手动选择符合要求的格式(同步操作,错误会被try-catch捕获) const targetFormat = ytdl.chooseFormat(videoInfo.formats, { quality: quality, filter: "audioonly" }); // 3. 根据选择的格式创建流并输出到响应 ytdl.downloadFromInfo(videoInfo, { format: targetFormat }).pipe(res); } catch (e) { res.status(500).send("Encountered Error: " + e.message); } });
为什么方案2更推荐?
拆分步骤后,你能更清晰地控制每一步的逻辑,不管是获取视频信息失败,还是格式选择失败,都会被try-catch直接捕获,不需要额外监听事件,代码的可读性和可维护性更好。
内容的提问来源于stack exchange,提问作者A Rogue Otaku
相关产品推荐
相关产品推荐

