[Day 19] Node http request

前言

今天来看看, node 怎麽进行一个 http request

正文

打开 http.js 这个 module

https://github.com/nodejs/node/blob/master/lib/http.js

查看呼叫 request 的方法

/**
 * Makes an HTTP request.
 * @param {string | URL} url
 * @param {HTTPRequestOptions} [options]
 * @param {Function} [cb]
 * @returns {ClientRequest}
 */
function request(url, options, cb) {
  return new ClientRequest(url, options, cb);
}

查看 ClientRequest 物件

// initiate connection
  if (this.agent) {
    this.agent.addRequest(this, optsWithoutSignal);
  } else {
		// 略
  }

跳过资料处理与设定, 直接看 this.agent.addRequest(this, optsWithoutSignal);

这里的 agent 是 TCP 连线的管理者, 这里先取 TCP 连线管理者存在, 可以直接使用的情况。

查看 addRequest

if (socket) {
    asyncResetHandle(socket);
    this.reuseSocket(socket, req);
    setRequestSocket(this, req, socket);
    ArrayPrototypePush(this.sockets[name], socket);
    this.totalSocketCount++;
 }

跳过取得 socket 的过程, 取得 socket 後, 调用 setRequestSocket 准备寄出资料。

function setRequestSocket(agent, req, socket) {
  req.onSocket(socket);
  const agentTimeout = agent.options.timeout || 0;
  if (req.timeout === undefined || req.timeout === agentTimeout) {
    return;
  }
  socket.setTimeout(req.timeout);
}

忽略後面处理逾时的部分, 查看 onSocket

ClientRequest.prototype.onSocket = function onSocket(socket, err) {
  // TODO(ronag): Between here and onSocketNT the socket
  // has no 'error' handler.
  process.nextTick(onSocketNT, this, socket, err);
};

发现其调用 node API 进入下一个阶段(何为阶段後面会提), 查看送到後面的回调函数 onSocketNT

function onSocketNT(req, socket, err) {
  if (req.destroyed || err) {
    req.destroyed = true;

    function _destroy(req, err) {
      if (!req.aborted && !err) {
        err = connResetException('socket hang up');
      }
      if (err) {
        req.emit('error', err);
      }
      req._closed = true;
      req.emit('close');
    }

    if (socket) {
      if (!err && req.agent && !socket.destroyed) {
        socket.emit('free');
      } else {
        finished(socket.destroy(err || req[kError]), (er) => {
          if (er?.code === 'ERR_STREAM_PREMATURE_CLOSE') {
            er = null;
          }
          _destroy(req, er || err);
        });
        return;
      }
    }

    _destroy(req, err || req[kError]);
  } else {
    tickOnSocket(req, socket);
    req._flush();
  }
}

跳过例外处理, 直接看 tickOnSocket(req, socket);

// 略
socket.on('error', socketErrorListener);
socket.on('data', socketOnData);
socket.on('end', socketOnEnd);
socket.on('close', socketCloseListener);
socket.on('drain', ondrain);
// 略

发现注册了一堆 callback function

明天进度

初看 node 的非同步处理, 我们挑了 http request 作为开始, 挖到底层後发现, 在 JS 部分做完应做的设定後主要是注册了一堆回调函数。

我们明天就来看看这些回调函数会被注册到哪吧 !

明天见 !


<<:  【後转前要多久】# Day04 HTML - 元素属性、以及Emmet语法

>>:  [Day4] API开发规格书

DAY28 Aidea专案实作-AOI瑕疵检测(3/4)

接续上一章的资料前处理後,今天要进入训练模型的流程,让我们继续看下去~ 载入相关套件 import ...

遇到困难解决困难,没有困难就给自己制造麻烦 -- 论try与expect

异常概述 在程序运行途中,经常会遇到各式各样的错误,这些错误被统称为异常。这类错误大部分都是Synt...

[Day22] 传值跟传参考概念

JavaScript 的型别有两种 - 纯值与物件,而在 JavaScript 中,赋予一个值到变数...

【day4】金鱼日本料理

每当想吃生鱼片的时候就会预订金鱼日本料理 位於靠近国父纪念馆的巷子里 还记得今年初的鲑鱼之乱时 总是...

Day 05 - Ramda

yo, what's up Ramda 是一个 Functional Programming 的函式...