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

异步函数执行流程解析:Node.js https.request代码疑问

关于Node.js中https.request Promise封装的执行流程疑问

以下是从Node.js官方文档获取的一段基于Promise封装https.request的代码:

return new Promise((resolve, reject) => {
    const req = https.request(URL, options, res => {
        let rawData = '';

        res.on('data', chunk => {
            rawData += chunk;
        });

        res.on('end', () => {
            resolve(rawData);
        });
    });

    req.on('error', err => {
        reject(new Error(err));
    });

    req.end();
});

我大致理解这段代码的逻辑:调用包含该代码的函数会返回一个Promise;执行https.request时传入回调函数,用于处理响应数据和连接结束事件,连接结束时会resolve外层Promise。但我有疑问:https.request之后的req.on('error')和req.end()代码何时执行?我有两种猜想:

  1. https.request返回Promise后立即执行后续代码,但这样可能会在请求完成前结束连接;
  2. https.request阻塞执行,直到resolve后才执行后续代码,类似await的效果,但这样无法在req.end()前通过req流上传文件,也不清楚如何获取上传后的响应。
    我希望明确这段代码的执行流程,结合async/Promise的特性解释原因,尤其是传入回调时https.request是否返回Promise、是否阻塞执行的问题。

核心结论先明确

  • https.request本身不返回Promise:它返回的是ClientRequest类型的可写流对象,和Promise完全无关。
  • https.request是非阻塞异步执行:调用后立刻返回,不会等待请求完成或响应到达,后续代码会同步执行。

完整执行流程拆解

  1. 调用封装函数,进入Promise构造函数
    当你调用这个封装函数时,会立刻创建并进入Promise的构造函数逻辑,构造函数内的代码是同步执行的。

  2. 执行https.request,获取req对象
    调用https.request(...)时:

    • Node.js会立刻发起异步的HTTP请求(底层交给操作系统处理网络操作,不会阻塞当前线程)。
    • 同时立刻返回ClientRequest实例,赋值给变量req。
    • 你传入的res => {...}回调函数不会立刻执行,它是响应到达时才会触发的异步回调。
  3. 同步执行req.on('error')和req.end()
    获取req对象后,后续的req.on('error', ...)和req.end()都是同步执行的:

    • req.on('error')只是给req流绑定一个错误监听事件,这一步瞬间完成,不会等待错误发生。
    • req.end()的作用是告诉Node.js:请求的写入阶段已完成(如果需要上传文件/数据,你可以在req.end()之前调用req.write()分块写入数据)。调用req.end()不会直接结束连接,Node.js会继续处理请求的发送、等待响应等后续异步逻辑。
  4. 封装函数返回pending状态的Promise
    当Promise构造函数内的所有同步代码执行完毕后,封装函数会返回这个Promise对象,此时Promise处于pending(等待)状态。

  5. 异步事件触发,改变Promise状态

    • 如果请求成功收到响应:触发https.request传入的res回调,接着通过res.on('data')拼接响应数据,当响应数据接收完毕时触发res.on('end'),调用resolve(rawData),Promise变为fulfilled(已完成)状态。
    • 如果请求过程中出错(比如DNS解析失败、连接超时、服务器错误):触发req的error事件,调用reject(new Error(err)),Promise变为rejected(已失败)状态。

对你的两个猜想的澄清

  1. 猜想1错误:req.end()是同步执行,但它不会提前结束连接。它只是结束请求的写入流,Node.js会继续处理请求的发送和响应接收,完全不会影响后续的异步逻辑。
  2. 猜想2错误:https.request是非阻塞的,不会等待Promise的resolve才执行后续代码。正因为它是非阻塞,你才可以在req.end()之前通过req.write()上传文件——比如你可以在req.on('error')之后、req.end()之前添加req.write(fileChunk)来分块上传数据,这完全符合流的使用逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:54:14