You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript Promise问题求助:http.get回调未执行及await实现疑问

问题原因分析

1. 同步循环阻塞事件循环

你的do-while是同步循环,移除break后会瞬间创建25000个Promise并发起HTTP请求。Node.js的事件循环机制中,同步代码优先执行,所有同步循环逻辑跑完前,http.get这类异步I/O的回调根本没机会被处理。同时,Node.js HTTP客户端默认对每个域名限制5个并发连接,瞬间发起上万请求会耗尽socket池,导致请求发不出去,服务器收不到请求、回调自然也不会执行。

2. 无效的"等待"逻辑

你用blnNext试图控制循环,但同步代码不会因为异步操作暂停——blnNext = false后,continue不会等Promise完成,循环直接进入下一轮,完全达不到"等上一个请求完成再发下一个"的目的。

3. 带break时能执行一次的原因

当有break时,循环只执行一次,同步代码很快跑完,事件循环有机会处理http.get的异步回调,所以能完成一次请求。


用async/await实现可控循环请求

下面提供两种常见实现方式,按需选择:

方案1:串行请求(逐个完成再发起下一个)

适合需要按顺序处理响应、或不想给服务器造成过大压力的场景:

const http = require('http'); // 确保引入http模块

async function runRequests() {
    const totalRequests = 25000;
    for (let intRequest = 1; intRequest <= totalRequests; intRequest++) {
        try {
            info.msg(`Request#${intRequest}`);
            info.msg("Creating promise");
            // await等待当前请求完成
            const data = await new Promise((myResolve, myError) => {
                const cstrURI = "http://localhost:8000/"
                            + "?cn=Tesla&cy=2024&cm=1&cd=8&ds=clickcomp&rt=10&u=1";
                http.get(cstrURI, res => {
                    let data = [];
                    const headerDate = res.headers 
                                    && res.headers.date 
                                    ? res.headers.date : 'no response date';
                    info.msg('Status Code:', res.statusCode);
                    info.msg('Date in Response header:', headerDate);

                    res.on("data", chunk => {
                        data.push(chunk);
                    });
                    res.on('end', () => {
                        info.msg('Response ended: ');
                        // 将Buffer数组转为字符串,方便查看内容
                        myResolve(Buffer.concat(data).toString());
                    });
                }).on("error", err => {
                    const strMsg = `ERROR:${err.message}`;
                    info.msg(defs.RED + strMsg + defs.RESET);
                    myError(strMsg);
                });
            });
            console.log(`myPromise.resolve(${data})`);
        } catch (strError) {
            console.log(`myPromise.reject(${strError})`);
            // 可选:遇到错误是否继续循环,这里选择继续执行后续请求
            continue;
        }
    }
}

// 启动执行
runRequests();

方案2:可控并发请求(同时发起N个请求)

如果需要更高执行效率,又不想压垮服务器,可以限制并发数:

const http = require('http');

async function runConcurrentRequests(totalRequests, concurrency = 10) {
    // 用信号量控制并发数
    const semaphore = new Array(concurrency).fill(Promise.resolve());

    for (let intRequest = 1; intRequest <= totalRequests; intRequest++) {
        // 找到信号量中已完成的位置,复用它发起新请求
        const availableIndex = semaphore.findIndex(p => p.isFulfilled || p.isRejected);
        semaphore[availableIndex] = semaphore[availableIndex].then(async () => {
            try {
                info.msg(`Request#${intRequest}`);
                info.msg("Creating promise");
                const data = await new Promise((myResolve, myError) => {
                    const cstrURI = "http://localhost:8000/"
                                + "?cn=Tesla&cy=2024&cm=1&cd=8&ds=clickcomp&rt=10&u=1";
                    http.get(cstrURI, res => {
                        let data = [];
                        const headerDate = res.headers 
                                        && res.headers.date 
                                        ? res.headers.date : 'no response date';
                        info.msg('Status Code:', res.statusCode);
                        info.msg('Date in Response header:', headerDate);

                        res.on("data", chunk => {
                            data.push(chunk);
                        });
                        res.on('end', () => {
                            info.msg('Response ended: ');
                            myResolve(Buffer.concat(data).toString());
                        });
                    }).on("error", err => {
                        const strMsg = `ERROR:${err.message}`;
                        info.msg(defs.RED + strMsg + defs.RESET);
                        myError(strMsg);
                    });
                });
                console.log(`myPromise.resolve(${data})`);
            } catch (strError) {
                console.log(`myPromise.reject(${strError})`);
            }
        });
    }

    // 等待所有请求完成
    await Promise.all(semaphore);
}

// 启动执行:总请求25000,并发10个
runConcurrentRequests(25000, 10);

关键说明

  • async/await必须在async函数中使用,通过await等待Promise完成,让异步代码逻辑更清晰,同时正确控制执行顺序。
  • 串行请求简单易维护,但执行速度慢;并发请求效率更高,但要根据服务器承受能力设置合理的并发数。
  • 原代码中data是Buffer数组,建议用Buffer.concat(data).toString()转为字符串,方便查看响应内容。

内容的提问来源于stack exchange,提问作者SPlatten

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:15:16