【NodeJs】启动本地服务遭遇端口占用怎么办⁉️

1,579 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

Dear,大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~


写作背景:

     在目前的众多前端工程化CLI中大多都提供在本地启动静态服务来辅助开发中页面的渲染,这些个CLI在遇到本地的端口占用的时候往往采用端口自增来重新启动服务。我相信这个现象在你开发项目的过程中也一定遇到过,如果没有遇到那你有没有发现控制台抛出包含“EADDRINUSE”的错误呢?

涉及知识点:

     在你在使用NodeJs做服务开发的过程中可能会遇到一个名为EADDRINUSE的错误,EADDRINUSEerror address in use的缩写,当我们重复启动同一个服务的时候会遭遇这个问题。意思就是已经有相同服务在监听这个端口、地址、处理器了,在NodeJs中文网的serverlisten模块下得知,处理这种问题的通常做法是延迟重试。下面是对应的示例代码:

server.on('error', (e) => {
  if (e.code === 'EADDRINUSE') {
    console.log('Address in use, retrying...');
    setTimeout(() => {
      server.close();
      server.listen(PORT, HOST);
    }, 1000);
  }
});

实现分析:

     通过上面的示例代码可以看出要想对端口实现自增后重启服务的效果的处理位置就在error的回调监听里面操作,当我们监听到抛出EADDRINUSE的错误后,将PORT自增后重新执行listen函数。同样在NodeJs中文网中提示:当且仅当在第一次调用 server.listen() 期间出现错误或调用 server.close() 时,才能再次调用 server.listen() 方法。 否则,将抛出 **ERR_SERVER_ALREADY_LISTEN **错误。

让启动服务不再尴尬:

  1. 构建一个基础的http服务:
const http = require('http');
let port = 3000;

const server = http.createServer((request, response) => {
    response.writeHead(200, {
        'Content-Type': 'text/plain;charset=utf-8',
    });
    response.end('欢迎访问');
});

server.listen(port, () => {
    console.log(`> Local: http://localhost:${port}`);
});
  1. 注册一个http服务失败的处理回调函数:
const onError = (e) => {
    if (e.code === 'EADDRINUSE') {
      //  TODO
    }
};

server.on('error', onError);
  1. 在失败的回调函数中当判断错误码为EADDRINUSEport进行自增:
const onError = (e) => {
    if (e.code === 'EADDRINUSE') {
        console.log(`Port ${port} is in use, trying another one...`);
        server.listen(++port);
    } else {
        console.log('其他错误:', e);
    }
};
  1. 完善代码,在成功启动服务和遇到其他失败的情况将失败的监听移除,以为我们将不再需要:
const http = require('http');
let port = 3000;

const server = http.createServer((request, response) => {
    response.writeHead(200, {
        'Content-Type': 'text/plain;charset=utf-8',
    });
    response.end('欢迎访问');
});

const onError = (e) => {
    if (e.code === 'EADDRINUSE') {
        console.log(`Port ${port} is in use, trying another one...`);
        server.listen(++port);
    } else {
        console.log('其他错误:', e);
    }
};

server.listen(port, () => {
    server.removeListener('error', onError);
    console.log(`> Local: http://localhost:${port}`);
});

扩展学习:

     Vite就是使用这种方式来处理端口占用的构建工具,具体的代码可以参考vite项目的packages\vite\src\node\http.ts模块中的httpServerStart()函数。


欢迎关注我的公众号“前端小鑫同学”,原创技术文章第一时间推送。