Cannot read properties of undefined (reading ‘length’)

One of the most common errors we record, “Cannot read properties of undefined (reading ‘length’)”, turned up in our own logs recently while looking into an issue with Microsoft Edge and the Facebook sdk. Let’s dive into this error, what it means, and how to fix it.
Breaking down the Message
TypeError: Cannot read properties of undefined (reading ‘length’)
In older browsers, this might also be shown as:
Cannot read property ‘length’ of undefined
TypeError is a subset of JavaScript Error that is thrown when code attempts to do something that does not exist on the target object.
This message indicates that our code expects to have an object with a length property, but that object was not present. length is commonly used on string and array , but a custom object could also have this property.
This is a blocking error , and script execution will stop when this error occurs.
Understanding the Root Cause
This error can be thrown for a lot of reasons, as it is incredibly common to reference the length property of string or array during everyday development. For example, if we had a function that acts on a string argument, but is called without a string, we would see this error.
In our case, we were intercepting a call to fetch , and we had assumed the url property would be a string.
But, dear developer, it was not always a string. ♂️.
We had some code like this that intercepted fetch requests and recorded some metadata if the request was correct. It looked something like this:
We were doing appropriate defensive type checking to make sure that the options argument had a valid url property. Unfortunately, fetch also accepts options to be any object with a stringifier: an object with a toString method. Like this:
In this case, options.url is undefined, so when we try to check options.url.length , it blows up with our error, “Cannot read property ‘length’ of undefined”. Ugh.
While this may be valid, it is a bit weird, right? We thought so too.
How to Fix It
So how do we fix this and prevent it from happening again?
1. Understand why your object is undefined

First and foremost, you need to understand why this happened before you can fix it. You are probably not doing exactly the same thing we are, so the reason your object is undefined may be somewhat different. Consider:
- Are you relying on a network response to be a certain shape?
- Are you processing user-input?
- Is an external function or library calling into your code?
Or maybe its just a logical bug somewhere in your code.
2. Add Defensive Checking

Anytime you don’t completely control the input into your code, you need to be defensively checking that arguments have the correct shape. API response change, functions get updated, and users do terrible, terrible things.
For instance, if you have a fetch request that receives a JSON response with a foo string property, you might have a defensive check that looks like this:
3. Monitor Your Environment

You’ll need to make sure that the issue is really fixed and that the problem stops happening. Mistakes happen, APIs change, and users are unpredictable. Just because your application works today, doesn’t mean an error won’t be discovered tomorrow. Tracking when exceptional events happen to your users gives you the context to understand and fix bugs faster. Check out TrackJS Error Monitoring for the fastest and easiest way to get started.
ReferenceError
The ReferenceError object represents an error when a variable that doesn’t exist (or hasn’t yet been initialized) in the current scope is referenced.
ReferenceError is a serializable object, so it can be cloned with structuredClone() or copied between Workers using postMessage() .
ReferenceError is a subclass of Error .
Constructor
Creates a new ReferenceError object.
Instance properties
Also inherits instance properties from its parent Error .
These properties are defined on ReferenceError.prototype and shared by all ReferenceError instances.
The constructor function that created the instance object. For ReferenceError instances, the initial value is the ReferenceError constructor.
Represents the name for the type of error. For ReferenceError.prototype.name , the initial value is «ReferenceError» .
Instance methods
Inherits instance methods from its parent Error .
Examples
Catching a ReferenceError
try let a = undefinedVariable; > catch (e) console.log(e instanceof ReferenceError); // true console.log(e.message); // "undefinedVariable is not defined" console.log(e.name); // "ReferenceError" console.log(e.stack); // Stack of the error >
Creating a ReferenceError
try throw new ReferenceError("Hello"); > catch (e) console.log(e instanceof ReferenceError); // true console.log(e.message); // "Hello" console.log(e.name); // "ReferenceError" console.log(e.stack); // Stack of the error >
Specifications
| Specification |
|---|
| ECMAScript Language Specification # sec-native-error-types-used-in-this-standard-referenceerror |
Browser compatibility
BCD tables only load in the browser
See also
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on May 26, 2023 by MDN contributors.
Your blueprint for a better internet.
Fix the unexpected end of input error in JavaScript

If you’re getting the unexpected end of input error when trying to execute a piece of JavaScript, this blog post is for you! A number of things can cause this error, we’ll walk you through the most often mistakes that lead towards causing these errors, and how to identify and fix this error. We will also discuss the unexpected end of JSON input error as a bonus.
Unexpected end of input error
The unexpected end of input error in JavaScript can occur for a variety of reasons. One common reason is that you have an extra comma in an array or object literal, which can cause the JavaScript engine to misinterpret the code. This can be especially tricky if you’re using a minified javascript which may remove whitespace, making it difficult to spot the error.
Another possibility is that you’re missing a semicolon at the end of a statement, which can also lead to this error. Again, this can be tough to spot if you’re not used to reading minified code.
The Problem
If you’re getting an unexpected end of input error in JavaScript, it’s likely that you’re missing a > or ; somewhere in your code. Here are a few examples that can cause these errors:
Code language: JavaScript (javascript)const example1 = function( ) < console.log("example1"); > // ?️ missing semicolon here const example2 = function( ) < console.log("example2"); ; // ?️ missing closing curly brace const arr = [1, 2 // ?️ missing closing square bracket const obj = age: 20 // ?️ missing closing curly brace
The Solution
This can be especially tricky if your code is spread out over multiple lines. Make sure to check that all of your curly braces have matching opening and closing symbols and that all of your semicolons are in the right place. If you’re still having trouble, try running your code through a linter like JSLint or ESLint to catch any potential errors.
Code language: JavaScript (javascript)const example1 = function( ) < console.log("example1"); >; // ?️ add missing semicolon here const example2 = function( ) < console.log("example2"); >; // ?️ add missing closing curly brace const arr = [1, 2]; // ?️ add missing closing square bracket const obj = age: 20>; // ?️ add missing closing curly brace
Unexpected end of JSON input error
If you have ever received unexpected end of JSON input error when trying to parse JSON data, you know how frustrating it can be. Few factors that can cause this error are:
One common cause of unexpected end of JSON input error is simply that the JSON data is not well-formed. This means that there are syntax errors in the JSON data itself.
Another common cause of this error is that the JSON data is not valid for the particular structure you are trying to parse it into. For instance, if you are trying to parse JSON data into a JavaScript object, but the JSON data contains invalid property names (such as – characters), then you will receive this error.
The Problem
Code language: JavaScript (javascript)const jsonData1 = JSON.stringify(< name: "codedamn" // ?️ missing comma here founder: "Mehul Mohan" >); const jsonData2 = "; // ?️ invalid json format console.log(JSON.parse(jsonData1)); // ⛔️ throws an error console.log(JSON.parse(jsonData2)); // ⛔️ throws an error
The Solution
There are a few different ways that can help you detect and fix this error:
- The most common solution is to add a trailing comma to the end of the string. This will ensure that the string is properly formatted and will be parsed correctly by your code.
- You can use a tool like jsonlint to validate your JSON data. If you see any syntax errors, simply fix them and try parsing the data again.
- Make sure that your JSON data is valid for the structure you are trying to parse it into.
Finally, if none of the above solutions work, then the most likely cause of the error is that your JSON data is too large for the particular parser you are using. For instance, if you are using the express JSON parser in Node.js, it has a limit of 100kb for the size of the JSON data it can parse. If your JSON data is larger than this, you will need to use a different parser.
Hopefully, one of the above solutions will help you fix the unexpected end of JSON input error in your own code.
Code language: JavaScript (javascript)const jsonData1 = JSON.stringify(< name: "codedamn", // ?️ add missing comma here founder: "Mehul Mohan" >); const jsonData2 = hello: "world">; // ?️ valid json format console.log(JSON.parse(jsonData1)); console.log(JSON.parse(jsonData2));
Conclusion
In conclusion, If you’re seeing the unexpected end of input error in your JavaScript code, it’s likely that you’re missing a closing brace somewhere. To fix this, simply check your code for any open braces and make sure that they all have corresponding closing braces. Once you’ve done this, the error should be fixed and your code should run without issue. We also discussed the unexpected end of JSON input error as a bonus in this blog post.
Thanks for reading! I hope you end up solving the issue and carry forward with your coding. If you have any questions or comments, please feel free to contact me.
Become The Best JavaScript Developer
Codedamn is the best place to become a proficient developer. Get access to hunderes of practice JavaScript courses, labs, and become employable full-stack JavaScript web developer.
Unlimited access to all platform courses
100+ practice projects included
ChatGPT Based Instant AI Help
Structured Full-Stack Web Developer Roadmap To Get A Job
Exclusive community for events, workshops
Sharing is caring
Did you like what Mridul Anand Singh wrote? Thank them for their work by sharing it on social media.
Руководство по обработке ошибок в Node.js
Ошибки есть в каждом коде. Мы перевели гайд разработчика Айо Исайя, в котором он рассказывает о системе ошибок и о том, как их устранять.
Раз вы читаете эту статью, вы, конечно, знакомы с концепцией ошибок в программировании. Это ошибки в коде, они же баги, которые приводят к сбою или неожиданному поведению программы. В отличие от некоторых языков, таких как Go и Rust, где вы вынуждены взаимодействовать с потенциальными ошибками на каждом этапе пути, в JavaScript и Node.js можно обойтись без согласованной стратегии обработки ошибок.
Однако именно такая стратегия делает жизнь проще. Цель статьи — познакомить вас с этими шаблонами для создания, доставки и обработки потенциальных ошибок. Шаблоны помогут обнаружить и обработать потенциальные ошибки в коде до развёртывания.
Что такое ошибки в Node.js
Ошибка в Node.js — это любой экземпляр объекта Error. Общие примеры включают встроенные классы ошибок: ReferenceError , RangeError , TypeError , URIError , EvalError и SyntaxError . Пользовательские ошибки также можно создать путём расширения базового объекта Error, встроенного класса ошибки или другой настраиваемой ошибки. При создании ошибок таким путём нужно передать строку сообщения, описывающую ошибку. К сообщению можно получить доступ через свойство message объекта. Объект Error также содержит свойства name и stack , которые указывают имя ошибки и точку в коде, в которой объект создаётся.
const userError = new TypeError("Something happened!"); console.log(userError.name); // TypeError console.log(userError.message); // Something happened! console.log(userError.stack); /*TypeError: Something happened! at Object. (/home/ayo/dev/demo/main.js:2:19) at node:internal/main/run_main_module:17:47 */
Функции объекта Error можно передать или вернуть из функции. Если бросить его с помощью throw , объект Error станет исключением. Когда вы передаёте ошибку из функции, она переходит вверх по стеку, пока исключение не будет поймано. В противном случае uncaught exception может обвалить всю работу.
Как обработать ошибку
Оптимальный способ обработки ошибок функции JavaScript зависит от того, выполняет ли эта функция синхронную или асинхронную операцию. Рассмотрим четыре общих шаблона, позволяющих обрабатывать ошибки функций в Node.js.
Исключения
Чаще всего ошибки функций обрабатывают путём генерации. В этом случае ошибка становится исключением, после чего её можно поймать где-нибудь в стеке с помощью блока try / catch . Если у ошибки есть разрешение всплывать в стеке, не будучи перехваченной, она преобразуется в формат uncaughtException , что приводит к преждевременному завершению работы приложения. Например, встроенный метод JSON.parse () выдаёт ошибку, если строковый аргумент не является допустимым объектом JSON.
function parseJSON(data) < return JSON.parse(data); >try < const result = parseJSON('A string'); >catch (err) < console.log(err.message); // Unexpected token A in JSON at position 0 >
Для использования этого шаблона в функциях нужно добавить ключевое слово throw перед экземпляром ошибки. Этот шаблон сообщения об ошибках и обработки идиоматичен для функций, выполняющих синхронные операции.
function square(num) < if (typeof num !== 'number') < throw new TypeError(`Expected number but got: $`); > return num * num; > try < square('8'); >catch (err) < console.log(err.message); // Expected number but got: string >
Колбэк с первым аргументом-ошибкой
Из-за своей асинхронной природы Node.js интенсивно использует функции колбэка для обработки большей части ошибок. Колбэк (обратный вызов) передаётся в качестве аргумента другой функции и выполняется, когда последняя завершает свою работу.
Node.js использует колбэк с первым аргументом-ошибкой в большинстве асинхронных методов, чтобы гарантировать проверку ошибок до результатов операции. Колбэк обычно является последним аргументом функции, инициирующей асинхронную операцию, и вызывается один раз при возникновении ошибки или получении результата:
function (err, result) <>
Первый аргумент зарезервирован для объекта ошибки. Если ошибка возникает в ходе асинхронной операции, она доступна через аргумент err при неопределённом результате. Однако, если ошибки не возникает, err будет иметь значение null или undefined , а result будет содержать ожидаемый результат операции. Этот шаблон работает, если прочитать содержимое файла с помощью встроенного метода fs.readFile ():
const fs = require('fs'); fs.readFile('/path/to/file.txt', (err, result) => < if (err) < console.error(err); return; >// Log the file contents if no error console.log(result); >);
Метод readFile () использует колбэк в качестве своего последнего аргумента, который, в свою очередь, соответствует подписи функции «первая ошибка». В этом сценарии result включает в себя содержимое файла, который читается, если ошибки не возникает. В противном случае он определяется как undefined , а аргумент err заполняется объектом ошибки, содержащим информацию о проблеме: файл не найден или недостаточно полномочий.
Как правило, методы, использующие колбэк для обработки ошибок, не могут определить, насколько важна выявленная ошибка. Они возвращают ошибку пользователю для обработки. Важно контролировать поток содержимого колбэка, проверять функцию на наличие ошибки, прежде чем пытаться получить доступ к результату операции.
Чтобы использовать шаблон колбэка с первым аргументом-ошибкой в собственных асинхронных функциях, нужно принять функцию в качестве последнего аргумента и вызвать её:
function square(num, callback) < if (typeof callback !== 'function') < throw new TypeError(`Callback must be a function. Got: $`); > // simulate async operation setTimeout(() => < if (typeof num !== 'number') < // if an error occurs, it is passed as the first argument to the callback callback(new TypeError(`Expected number but got: $`)); return; > const result = num * num; // callback is invoked after the operation completes with the result callback(null, result); >, 100); >
Любой вызывающий функцию square должен пройти через колбэк, чтобы получить доступ к нужному результату или ошибке.
Не нужно непосредственно обрабатывать ошибку в функции колбэка. Её можно распространить вверх по стеку, передав на другой колбэк. Но сначала убедитесь, что вы не генерируете исключение внутри функции. Асинхронное исключение невозможно отследить, потому что окружающий блок try / catch завершается до выполнения колбэка. Следовательно, исключение будет распространяться на вершину стека, что приведёт к завершению работы приложения. Исключение — когда обработчик зарегистрирован для process.on (‘uncaughtException’) .
try < square('8', (err, result) => < if (err) < throw err; // not recommended >console.log(result); >); > catch (err) < // This won't work console.error("Caught error: ", err); >

Отклонение обещаний
Обещания в JavaScript — это актуальный способ выполнения асинхронных операций в Node.js. Они предпочтительнее колбэков из-за лучшего потока, который соответствует современным способам анализа программ, особенно с шаблоном async / await . Любой API-интерфейс Node.js, использующий колбэки с ошибкой для асинхронной обработки ошибок, может быть преобразован в обещания с помощью встроенного метода util.promisify () . Например, заставить метод fs.readFile () использовать обещания можно так:
const fs = require('fs'); const util = require('util'); const readFile = util.promisify(fs.readFile);
Переменная readFile — это версия fs.readFile () с обещаниями, в которой отклонения обещаний используются для сообщения об ошибках. Эти ошибки можно отследить, связав метод catch :
readFile('/path/to/file.txt') .then((result) => console.log(result)) .catch((err) => console.error(err));
Также можно использовать обещанные API в функциях async . Так выглядит основной способ использования обещаний в современном JavaScript: в нём код читается как синхронный, и для обработки ошибок применяют знакомый механизм try / catch . Перед асинхронным запуском важно использовать await , чтобы обещание было выполнено или отклонено до того, как функция возобновит выполнение. При отклонении обещания выражение await выбрасывает отклонённое значение, которое впоследствии попадает в окружающий блок catch .
(async function callReadFile() < try < const result = await readFile('/path/to/file.txt'); console.log(result); >catch (err) < console.error(err); >>)();
Обещанияможно использовать в асинхронных функциях, возвращая обещание из функции и помещая код функции в обратный вызов обещания. Если есть ошибка, её стоит отклонить (reject) с помощью объекта Error. В противном случае можно разрешить (resolve) обещание с результатом, чтобы оно было доступно в цепочке метода .then или напрямую как значение функции async при использовании async / await .
function square(num) < return new Promise((resolve, reject) => < setTimeout(() =>< if (typeof num !== 'number') < reject(new TypeError(`Expected number but got: $`)); > const result = num * num; resolve(result); >, 100); >); > square('8') .then((result) => console.log(result)) .catch((err) => console.error(err));
Источники событий
Другой шаблон, подходящий для работы с длительными асинхронными операциями, которые могут приводить к множественным ошибкам или результатам, — это возврат EventEmitter из функции и выдача события как для успешного, так и для неудачного случая:
const < EventEmitter >= require('events'); function emitCount() < const emitter = new EventEmitter(); let count = 0; // Async operation const interval = setInterval(() =>< count++; if (count % 4 == 0) < emitter.emit( 'error', new Error(`Something went wrong on count: $`) ); return; > emitter.emit('success', count); if (count === 10) < clearInterval(interval); emitter.emit('end'); >>, 1000); return emitter; >
Функция emitCount () возвращает новый эмиттер событий, который сообщает об успешном исходе в асинхронной операции. Она увеличивает значение переменной count и каждую секунду генерирует событие успеха и событие ошибки, если значение count делится на 4. Когда count достигает 10, генерируется событие завершения. Этот шаблон позволяет передавать результаты по мере их поступления вместо ожидания завершения всей операции.
Вот как можно отслеживать и реагировать на каждое из событий, генерируемых функцией emitCount () :
const counter = emitCount(); counter.on('success', (count) => < console.log(`Count is: $`); >); counter.on('error', (err) => < console.error(err.message); >); counter.on('end', () => < console.info('Counter has ended'); >);
Функция колбэка для каждого прослушивателя событий выполняется независимо, как только событие генерируется. Событие ошибки (error) — это особый случай для Node.js, потому что при отсутствии прослушивателя процесс Node.js выходит из строя. Вы можете закомментировать прослушиватель событий ошибки выше и запустить программу, чтобы увидеть, что произойдёт.

Расширение объекта ошибки
Необходимо создавать собственные пользовательские классы ошибок, чтобы лучше отражать разные типы ошибок: класс ValidationError для ошибок, возникающих при проверке пользовательского ввода, класс DatabaseError для операций с базами данных, TimeoutError для операций, для которых истекло назначенное им время ожидания.
Пользовательские классы ошибок, расширяющие объект Error , сохранят основные свойства ошибки: сообщение ( message ), имя ( name ) и стек ( stack ). Но у них есть собственные свойства. ValidationError можно улучшить, добавив значимые свойства — часть ввода, вызвавшую ошибку.
Вот как можно расширить встроенный объект Error в Node.js:
class ApplicationError extends Error < constructor(message) < super(message); // name is set to the name of the class this.name = this.constructor.name; >> class ValidationError extends ApplicationError < constructor(message, cause) < super(message); this.cause = cause >>
Класс ApplicationError — общая ошибка, а класс ValidationError представляет любую ошибку, возникающую при проверке ввода данных пользователем. Он наследуется от класса ApplicationError и дополняет его свойством cause для указания ввода, вызвавшего ошибку. Пользовательские классы ошибки можно использовать, как и обычные:
function validateInput(input) < if (!input) < throw new ValidationError('Only truthy inputs allowed', input); >return input; > try < validateInput(userJson); >catch (err) < if (err instanceof ValidationError) < console.error(`Validation error: $, caused by: $`); return; > console.error(`Other error: $`); >

Ключевое слово instanceof следует использовать для проверки конкретного типа ошибки. Не используйте имя ошибки для проверки типа, как в err.name === ‘ValidationError’ : это не сработает, если ошибка получена из подкласса ValidationError .
Типы ошибок
Типы ошибок можно разделить на две основные категории: ошибки программиста и операционные проблемы. К первому типу можно отнести неудачные или неправильные аргументы функции, в то время как временные сбои при работе с внешними API однозначно относятся ко второй категории.
Операционные ошибки
Операционные ошибки — это предсказуемые ошибки, которые возникают в процессе выполнения приложения. Это не обязательно баги, чаще это даже внешние обстоятельства, способные нарушить ход выполнения программы. В таких случаях можно полностью понять влияние ошибки на процессы:
- Запрос API не выполняется по какой-либо причине (например, сервер не работает или превышен лимит скорости).
- Соединение с базой данных потеряно, например, из-за неисправного сетевого соединения.
- ОС не может выполнить запрос на открытие файла или запись в него.
- Пользователь отправляет на сервер недопустимые данные: неверный номер телефона или адрес электронной почты.
Ошибки программиста
Ошибки программиста — это ошибки в логике или синтаксисе программы, которые можно исправить только путём изменения исходного кода. Ошибки этого типа невозможно обработать, потому что это недочёты в программе:
- Синтаксические ошибки: незакрытая фигурная скобка.
- Ошибки типа при попытке сделать что-то неправильное: выполнение операций с операндами несовпадающих типов.
- Неверные параметры при вызове функции.
- Ссылки на ошибки при неправильном написании имени переменной, функции или свойства.
- Попытка получить доступ к местоположению за концом массива.
- Неспособность обработать операционную ошибку.
Обработка операционных ошибок
Операционные ошибки в большинстве случаев предсказуемы. Их обработка — это рассмотрение вероятности неудачного завершения операции, возможных причин и последствий. Рассмотрим несколько стратегий обработки операционных ошибок в Node.js.
Сообщить об ошибке в стек
Во многих случаях лучше остановить выполнение программы, очистить все незавершённые процессы и сообщить об ошибке в стек. Зачастую это единственный способ исправить ошибку, когда функция, в которой она возникла, находится дальше по стеку.
Повторить операцию
Сетевые запросы к внешним службам иногда могут завершаться ошибкой, даже если запрос полностью верен. Это случается из-за сбоя и неполадках сети или перегрузке сервера. Можно повторить запрос несколько раз, пока он не будет успешно завершён или пока не будет достигнуто максимальное количество повторных попыток. Первое, что нужно сделать, — это определить, уместно ли повторить запрос. Если исходный код состояния HTTP ответа — 500, 503 или 429, повторте запрос через некоторое время.
Проверьте, присутствует ли в ответе HTTP-заголовок Retry-After. Он указывает на точное время ожидания перед выполнением последующего запроса. Если его нет, необходимо отложить последующий запрос и постепенно увеличивать временной промежуток для каждой повторной попытки. Этот метод известен как стратегия экспоненциального отката. Нужно ещё определить максимальное время задержки и число запросов до отказа от дальнейших попыток.
Отправить ошибку клиенту
По умолчанию пользователи вводят данные неправильно. Поэтому первое, что нужно сделать перед запуском каких-либо процессов, — проверить введённые данные и незамедлительно сообщить пользователю о любых ошибках. При обработке ошибок клиента обязательно включите всю информацию, необходимую для создания сообщения об ошибке и имеющую смысл для пользователя.
Прервать программу.
В случае неисправимых системных ошибок разумный выход — зарегистрировать ошибку и немедленно завершить работу программы. Если исключение невозможно исправить на уровне JavaScript, то, возможно, не получится корректно завершить работу сервера. Тогда нужен системный администратор, способный всё исправить.
Предотвращение ошибок программиста
Ошибки программиста сами по себе не могут быть обработаны, потому что их причина в коде или в логике. Однако ошибаться можно реже.
Принять TypeScript
TypeScript — это строго типизированное надмножество JavaScript. Основная цель его проектирования — статическая идентификация потенциально ошибочных конструкций без штрафных санкций во время выполнения. Принимая TypeScript в проекте (с максимально возможными параметрами компилятора), можно устранить целый класс ошибок программиста в ходе компиляции.
Когда проект на TypeScript, такие ошибки, как undefined is not a function , синтаксические или ссылочные ошибки, исчезают из кодовой базы. Перенос на TypeScript можно выполнять постепенно. Для быстрой миграции есть инструмент ts-migrate.
Определить поведение для неверных параметров
Многие ошибки возникают из-за передачи неверных параметров. Это может быть связано не только с очевидными ошибками, такими как передача строки вместо числа, но и с небольшими погрешностями, когда аргумент функции имеет правильный тип, но выходит за пределы диапазона, который функция способна обработать. Когда функция вызывается таким образом, она может выдать неверное значение, например NaN . Когда сбой обнаруживается, сперва трудно определить его причину.
При работе с неверными параметрами и определяйте их поведение, либо выдавая ошибку, либо возвращая специальное значение, такое как null , undefined или -1 , когда проблема может быть решена локально. Первый вариант— это подход, используемый JSON.parse () , который выдаёт исключение SyntaxError , если строка для синтаксического анализа недействительна. Второй вариант — метод string.indexOf () .
Автоматизированное тестирование
Автоматизированные наборы тестов повышает вероятность исправления ошибок. Тесты помогают выяснить, как функция работает с нетипичными значениями. Для модульного тестирования подходят среды, такие как Jest или Mocha.
Неперехваченные исключения и необработанные отклонения обещаний
Неперехваченные исключения и необработанные отклонения обещаний вызываются ошибками программиста. Событие uncaughtException генерируется, когда исключение не перехватывается до того как достигнет цикла обработки событий. При обнаружении неперехваченного исключения приложение немедленно выходит из строя. Для переопределения такого поведения всегда можно добавить обработчик события:
// unsafe process.on('uncaughtException', (err) => < console.error(err); >);
Но неперехваченное исключение указывает на то, что приложение находится в неопределённом состоянии. Поэтому попытка возобновить работу в обычном режиме без восстановления после ошибки небезопасна и может привести к утечке памяти и зависанию сокетов. Лучше использовать обработчик uncaught Exception для очистки всех выделенных ресурсов, закрытия соединений и ведения лога ошибок для оценки перед завершением процесса.
// better process.on('uncaughtException', (err) => < Honeybadger.notify(error); // log the error in a permanent storage // attempt a gracefully shutdown server.close(() =>< process.exit(1); // then exit >); // If a graceful shutdown is not achieved after 1 second, // shut down the process completely setTimeout(() => < process.abort(); // exit immediately and generate a core dump file >, 1000).unref() >);
Событие unhandledRejection генерируется, когда отклонённое обещание не обрабатывается блоком catch . В отличие от uncaughtException , эти события не вызывают немедленного сбоя приложения. Однако необработанные отклонения обещаний сейчас признаны устаревшими и могут немедленно завершить процесс в следующих релизах Node.js. Отслеживать необработанные отклонения обещаний можно с помощью прослушивателя событий unhandledRejection :
process.on('unhandledRejection', (reason, promise) => < Honeybadger.notify(< message: 'Unhandled promise rejection', params: < promise, reason, >, >); server.close(() => < process.exit(1); >); setTimeout(() => < process.abort(); >, 1000).unref() >);
Серверы необходимо запускать с помощью диспетчера процессов, который автоматически перезапустит их в случае сбоя. Распространённый вариант — PM2, но для Linux существуют также systemd и upstart , а пользователи Docker могут использовать собственную политику перезапуска. По завершении всех процессов стабильное обслуживание будет восстановлено почти мгновенно, а у вас будт информация о неперехваченном исключении. Можно запутсить несколько процессов и применить балансировщик нагрузки для распределения входящих запросов. Это поможет предотвратить простои.
Централизованная отчётность об ошибках
Ни одна стратегия обработки ошибок не будет полной без надёжной стратегии ведения журнала ошибок. Когда происходит сбой, важно узаписать как можно больше информации о проблеме. Централизация логов позволяет оценить, что происходит в коде.
Honeybadger предоставляет всё необходимое для отслеживания ошибок. Интегрируется так:
Установите пакет
Используйте npm для установки пакета:
$ npm install @honeybadger-io/js —save
Импортируйте библиотеку
Импортируйте библиотеку и настройте её с помощью ключа API, чтобы получать сообщения об ошибках:
const Honeybadger = require('@honeybadger-io/js'); Honeybadger.configure(< apiKey: '[ YOUR API KEY HERE ]' >); Сообщите об ошибках Метоодом notify (): try < // . error producing code >catch(error)
Просмотрите полную документацию или ознакомьтесь с образцом Node.js / Express на GitHub.
Без обработки ошибок не бывает надёжного софта.
Спасибо за внимание и удачного кода!