简体   繁体   English

为什么我在 NodeJS 中收到“初始化前无法访问‘服务器’”错误?

[英]Why am I getting "Cannot access 'server' before initialization" error in NodeJS?

I am getting the dreaded Cannot access 'server' before initialization error in code that is identical to code that's running in production.在与生产中运行的代码相同的代码中出现Cannot access 'server' before initialization

The only things that have changed are my OS version (macOS 10.11->10.14) my NodeJS version (10->12) and my VSCode launch.json , but I cannot see anything in either that would cause an issue.唯一改变的是我的操作系统版本(macOS 10.11->10.14)我的 NodeJS 版本(10->12)和我的 VSCode launch.json ,但我看不到任何会导致问题的东西。 My Node version went from 10 to 12, but in production it went from 8 to 15 without issue.我的 Node 版本从 10 到 12,但在生产中它从 8 到 15 没有问题。 I routinely keep launch.json pretty sparse, and the same error happens using node server in Terminal.我经常保持launch.json非常稀疏,并且在终端中使用node server也会发生同样的错误。

Here is the offending code.这是有问题的代码。 The issue occurs because I have shutdown() defined before server and it references server .出现此问题是因为我在server之前定义了shutdown()并且它引用了server It's written to add an event-handler and then cause the event.编写它是为了添加一个事件处理程序,然后引发事件。 Yes, it could be refactored but it already works.是的,它可以被重构,但它已经可以工作了。 It works, really.它确实有效。 In 21 instances spread over 7 servers.在 21 个实例中分布在 7 个服务器上。

I have tried changing the declaraion/init of server from const to var but that does not fix it.我尝试将server的声明/初始化从const更改为var但这并不能解决它。 As mentioned, this is code that's running in prod ?如前所述,这是在 prod 中运行的代码 What's wrong with my environment?我的环境有什么问题?

Maybe a better question is: why did this ever work?也许更好的问题是:为什么这会奏效?

'use strict'

const fs = require('fs');
const https = require('https');
const cyp = require('crypto').constants;
const stoppable = require('./common/stoppable.js');
const hu = require('./common/hostutil');

process.on('uncaughtException', err => {
  wslog.error(`Uncaught Exception: ${err} ${err.stack}`);
  shutdown();
});

process.on('unhandledRejection', (reason, p) => {
  wslog.error(`Unhandled Promise Rejection: ${reason} - ${p}`);
});

// 'shutdown' is a known static string sent from node-windows wrapper.js if the service is stopped
process.on('message', m => {
  if (m == 'shutdown') {
    wslog.info(`${wsconfig.appName} has received shutdown message`);
    shutdown();
  }
});

process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
process.on('SIGHUP', shutdown);

function shutdown() {
  httpStatus = 503; // Unavailable
  wslog.info(`${wsconfig.appName} httpStatus now ${httpStatus} - stopping server...`);
// Error happens on this next line; It should not execute till after server is running already
  server.on('close', function () {
    wslog.info(`${wsconfig.appName} HTTP server has stopped, now exiting process.`);
    process.exit(0)
  });
  server.stop();
}

// Init and start the web server/listener
var combiCertFile = fs.readFileSync(wsconfig.keyFile, 'utf8');
var certAuthorityFile = fs.readFileSync(wsconfig.caFile, 'utf8');

var serverOptions = {
  key: combiCertFile,
  cert: combiCertFile,
  ca: certAuthorityFile,
  passphrase: wsconfig.certPass,
  secureOptions: cyp.SSL_OP_NO_TLSv1 | cyp.SSL_OP_NO_TLSv1_1
};

var server = https.createServer(serverOptions, global.app)
  .listen(wsconfig.port, function () {
    wslog.info(`listening on port ${wsconfig.port}.`);
  });

server.on('clientError', (err, socket) => {
  if (err.code === 'ECONNRESET' || !socket.writable) { return; }
  // ECONNRESET was already logged in socket.on.error. Here, we log others.
  wslog.warn(`Client error: ${err} ${err.stack}`);
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

server.on('error', (err)=>{
  if ( err.code === 'EADDRINUSE' ) {
    wslog.error(`${err.code} FATAL - Another ${wsconfig.appName} or app is using my port! ${wsconfig.port}`);
  } else {
    wslog.error(`${err.code} FATAL - Server error: ${err.stack}`);
  }
  shutdown();
})

combiCertFile = null;
certAuthorityFile = null;

// Post-instantiation configuration required (may differ between apps: need an indirect way to plug in app-specific behavior)
stoppable(server, wsconfig.stopTimeout);

// Load all RESTful endpoints
const routes = require('./routes/');

This is a runtime error, which happens only in a very specific situation.这是一个运行时错误,仅在非常特定的情况下才会发生。 But actually this exact error shouldn't happen with var server =... but only with const server =... or let server =... .但实际上这个确切的错误不应该发生在var server =...上,而只发生在const server =...let server =...上。 With var server =... the error message should say "Cannot read properties of undefined"使用var server =...错误消息应显示"Cannot read properties of undefined"

What happens怎么了

You have an error handler for uncaughtException which is calling shutdown() and in shutdown() you are referencing your server .您有一个uncaughtException的错误处理程序,它正在调用shutdown()并且在shutdown()中您正在引用您的server But consider what happens if your code throws an exception before you initialized your server .但是请考虑如果您的代码在初始化server之前引发异常会发生什么。 For instance if your cert or key cannot be read from the disk, cert or key are invalid... So nothing will be assigned to server , and an exception will be raised.例如,如果无法从磁盘读取您的证书或密钥,则证书或密钥无效......因此不会将任何内容分配给server ,并且会引发异常。

Then the handler for your uncaught exception will fire and call the shutdown() function, which then tries to access the server , which of course hasn't been initialized yet.然后,未捕获异常的处理程序将触发并调用shutdown() function,然后尝试访问当然尚未初始化的server

How to fix怎么修

Check what the unhandled exception is, that is thrown before your server is initialized and fix it.检查未处理的异常是什么,在初始化服务器之前抛出并修复它。 In your production environment, there is probably no exception, because the configuration and environment is properly set up.在您的生产环境中,可能也不例外,因为配置和环境设置正确。 But there is at least one issue in your develepment environment, which causes an exception.但是您的开发环境中至少存在一个问题,这会导致异常。

Difference between var and const varconst的区别

And the difference between var server =... and const server =... is quite a subtle one. var server =...const server =...之间的区别非常微妙。 For both, the declaration of the variable is hoisted up to the top of their respective scope.对于两者,变量的声明都被提升到它们各自的 scope 的顶部。 In your case it's always global, also for const .在您的情况下,它始终是全局的,对于const也是如此。 But variables declared as var are assigned a value of undefined whereas variables declared as let/const are not initialized at all.但是声明为var的变量被赋值为undefined ,而声明为let/const的变量根本没有被初始化。

You can easily reproduce this error if you uncomment either error1 or error2 in the following code.如果您在以下代码中取消注释error1error2 ,您可以轻松地重现此错误。 But error3 alone won't produce this ReferenceError because bar will already be initialized.但是单独的error3不会产生这个ReferenceError因为bar已经被初始化了。 You can also replace const bar = with var bar = and you will see, that you get a different error message.您也可以将const bar =替换为var bar = ,您会看到,您会收到不同的错误消息。

process.on("uncaughtException", err => {
  console.log("uncaught exception");
  console.log(err);
  foo();
});


function foo() {
  console.log("foo");
  console.log(bar.name);
}

function init() {
  // throw new Error("error1");
  return { name: "foobar"}
}

// throw new Error("error2");
const bar = init();

//throw new Error("error3");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我正在尝试删除反应中的笔记,但我收到一个错误,您无法在初始化之前访问新笔记? - I am trying to delete a note in react but I am getting an error that you cannot access new notes before initialization? 收到错误:`ReferenceError:在初始化之前无法访问'imported const'' in react - Getting an error: `ReferenceError: Cannot access 'imported const' before initialization` in react 在初始化错误之前无法访问“人” - Cannot access 'person' before initialization Error 我在服务器控制台中构建反应应用程序时出现此错误“未捕获的 ReferenceError:在初始化之前无法访问'__WEBPACK_DEFAULT_EXPORT__'” - I have this error in building react app in server console "Uncaught ReferenceError: Cannot access '__WEBPACK_DEFAULT_EXPORT__' before initialization" [NodeJs][Sequelize] ReferenceError:初始化前无法访问“ModelName” - [NodeJs][Sequelize] ReferenceError: Cannot access 'ModelName' before initialization 为什么我在 NodeJS 中收到这个意外的 HTTP 错误 - Why am I getting this UNEXPECTED HTTP error in NodeJS 使用 Firebase 和 JavaScript 时出现“初始化前无法访问 'firebase'”错误 - Getting the “Cannot access 'firebase' before initialization” error when using Firebase with JavaScript 为什么`const arg = arg;`会产生“初始化前无法访问”错误? - Why does `const arg = arg;` produce a "Cannot access before initialization" error? 为什么我收到错误缺失; 声明之前 - Why am I getting the error Missing ; before statement 为什么我在终端 Nodejs 中没有得到 output? - Why i am not getting output in teminal Nodejs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM