NodeJS中如何让代码在所有request异步请求完成后再执行
问题原因
你遇到的问题是因为request库默认是回调式异步非阻塞接口,遍历发起请求时JS不会等待回调函数执行,就会直接运行后续的console.log("the end")逻辑。
解决思路
将所有异步请求包装为Promise对象,再通过Promise.all批量等待所有异步任务执行完成后再执行打印逻辑。
改造后的完整代码
// 原项目的API_KEY、urlTelegram、NUMERO_DE_ELEMENTOS全局变量保持不变即可 function getValoresAcao(acoes) { // 把每个股票的请求任务转为Promise,收集为任务数组 const requestTasks = acoes.map(acao => getValorAcao(acao)); // 等待所有任务执行完成 Promise.all(requestTasks) .then(() => { console.log("the end"); }) .catch(err => { console.error("部分请求执行出错:", err); }); } function getValorAcao(acao) { // 把整个异步逻辑包装为Promise返回 return new Promise((resolve, reject) => { const url = 'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&parse_mode=HTML&symbol='+acao+'&apikey='+API_KEY; request(url, { json: true }, (err, res, body) => { if (err) { console.log(err); return reject(err); } let contador = 0; let valorDeDoisDias = []; const dailyJsonObject = body["Time Series (Daily)"]; const objectKeysArray = Object.keys(dailyJsonObject); objectKeysArray.forEach(function(objKey) { const objValue = dailyJsonObject[objKey]; if (contador < NUMERO_DE_ELEMENTOS ) { const valorFechamento = objValue["4. close"]; console.log(valorFechamento); contador = contador + 1; valorDeDoisDias.push(valorFechamento); } }); const textoDiferenca = getDiferencaEmPorcentagem(valorDeDoisDias); const bigString = "" + acao + " | " + valorDeDoisDias[0] + " | " + textoDiferenca; request(urlTelegram + bigString, { json: true }, (err, res, bodyTelegram) => { if (err) { console.log(err); return reject(err); } console.log(bodyTelegram); // 该股票的所有逻辑处理完成,标记当前Promise完成 resolve(); }); }); }); } function getDiferencaEmPorcentagem(valprDeDoisDias) { let myString = ""; const valorDiaAnterior = valprDeDoisDias[0]; const valorDiaMaisRecente = valprDeDoisDias[1]; myString = (valorDiaAnterior - valorDiaMaisRecente ) / valorDiaMaisRecente * 100; myString = myString.toFixed(2); console.log(myString); return myString + "%"; }
可选优化:async/await 写法
如果运行环境支持ES7的async/await语法,getValoresAcao可以改写为更简洁的版本:
async function getValoresAcao(acoes) { try { const requestTasks = acoes.map(acao => getValorAcao(acao)); await Promise.all(requestTasks); console.log("the end"); } catch (err) { console.error("部分请求执行出错:", err); } }
注意事项
如果希望某一个请求出错时不影响其他请求的等待逻辑,可以在getValorAcao的Promise内部捕获错误后直接resolve,避免Promise.all直接中断执行。
内容的提问来源于stack exchange,提问作者fabiobh
相关产品推荐
相关产品推荐

