今天來看看, 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 部分做完應做的設定後主要是註冊了一堆回調函數。
我們明天就來看看這些回調函數會被註冊到哪吧 !
明天見 !