如何使用axios发起多个串行请求 实现NodeJS音频文件顺序处理
解决方案
问题根源
你当前代码无法串行执行的核心原因有两个:
https.get是回调风格的API,本身不会返回Promise,你对它使用await不会产生阻塞效果,循环会直接进入下一轮axios.post没有被await,仅用.then处理回调的话,程序不会等待接口返回就进入下一次循环
修复方案
统一使用Promise + async/await 风格编写异步逻辑,确保每一轮循环的所有操作都执行完成后再进入下一轮,推荐直接用axios统一处理所有请求,避免混合不同异步风格导致的逻辑混乱:
async function myFunction(client){ // 原有其余逻辑保持不变 const fileC = database() const vars = {"variable":"my_variable"} const url = "my_url" const fileList = [] await fileC.find({}).forEach(f=>fileList.push(f)) // 串行遍历处理所有文件 for (const f of fileList) { try { // 步骤1:下载音频文件,await等待下载完成 const fileRes = await axios.get(f.file_location, { responseType: 'stream' }) // 步骤2:构造请求表单 const form = new FormData() Object.keys(vars).forEach(key => form.append(key, vars[key])) form.append("file", fileRes.data, f.file_name) // 步骤3:调用外部API,await等待处理完成返回结果 const apiRes = await axios.post(url, form, { headers: form.getHeaders(), maxBodyLength: Infinity }) // 步骤4:展示处理结果 console.log(`文件${f.file_name}处理结果:`, apiRes.data.val) } catch (err) { // 单个文件处理错误不会中断后续文件处理 console.error(`文件${f.file_name}处理失败:`, err.message) } } }
可选方案:保留https.get的写法
如果你需要保留原来的https.get下载文件的逻辑,只需要把它封装成Promise即可正常await:
// 封装https.get为Promise格式 function downloadFile(url) { return new Promise((resolve, reject) => { https.get(url, (res) => { if (res.statusCode === 200) return resolve(res) reject(new Error(`下载失败,状态码:${res.statusCode}`)) }).on('error', reject) }) } // 循环部分修改为 for (const f of fileList) { try { const fileStream = await downloadFile(f.file_location) const form = new FormData() Object.keys(vars).forEach(key=>form.append(key,vars[key])) form.append("file", fileStream, f.file_name) const apiRes = await axios.post(url,form,{headers:form.getHeaders(),maxBodyLength:Infinity}) console.log(`文件${f.file_name}处理结果:`, apiRes.data.val) } catch (err) { console.error(`文件${f.file_name}处理失败:`, err.message) } }
以上两种方案都可以保证每一轮循环完全执行完成后才会进入下一轮,不会出现并发调用API的问题。
内容的提问来源于stack exchange,提问作者MikelDeepLearner
相关产品推荐
相关产品推荐

