update promises
This commit is contained in:
74
docs/javascript/07-errors/01-try-catch.md
Normal file
74
docs/javascript/07-errors/01-try-catch.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Обработка ошибок, "try..catch"
|
||||
Конструкция `try..catch` позволяет обрабатывать ошибки во время исполнения кода. Она позволяет запустить код и перехватить ошибки, которые могут в нём возникнуть.
|
||||
|
||||
Секций `catch` или `finally` может не быть, то есть более короткие конструкции `try..catch` и `try..finally` также корректны.
|
||||
|
||||
Объекты ошибок содержат следующие свойства:
|
||||
- `message` – понятное человеку сообщение.
|
||||
- `name` – строка с именем ошибки (имя конструктора ошибки).
|
||||
- `stack` (нестандартное, но хорошо поддерживается) – стек на момент ошибки.
|
||||
|
||||
Если объект ошибки не нужен, мы можем пропустить его, используя `catch {` вместо `catch(err) {`.
|
||||
|
||||
Мы можем также генерировать собственные ошибки, используя оператор `throw`. Аргументом `throw` может быть что угодно, но обычно это объект ошибки, наследуемый от встроенного класса `Error`. Подробнее о расширении ошибок см. в следующей главе.
|
||||
|
||||
Проброс исключения – это очень важный приём обработки ошибок: блок `catch` обычно ожидает и знает, как обработать определённый тип ошибок, поэтому он должен пробрасывать дальше ошибки, о которых он не знает.
|
||||
|
||||
Даже если у нас нет `try..catch`, большинство сред позволяют настроить «глобальный» обработчик ошибок, чтобы ловить ошибки, которые «выпадают наружу». В браузере это window.onerror.
|
||||
|
||||
**`try..catch` работает синхронно**
|
||||
|
||||
|
||||
## try…catch…finally
|
||||
```js
|
||||
try {
|
||||
//... пробуем выполнить код...
|
||||
} catch(e) {
|
||||
//... обрабатываем ошибки ...
|
||||
} finally {
|
||||
//... выполняем всегда ...
|
||||
}
|
||||
```
|
||||
## Оператор «throw»
|
||||
Оператор throw генерирует ошибку.
|
||||
|
||||
```js
|
||||
let json = '{ "age": 30 }'; // данные неполны
|
||||
try {
|
||||
let user = JSON.parse(json); // <-- выполнится без ошибок
|
||||
if (!user.name) {
|
||||
throw new SyntaxError("Данные неполны: нет имени"); // (*)
|
||||
}
|
||||
alert( user.name );
|
||||
} catch(e) {
|
||||
alert( "JSON Error: " + e.message ); // JSON Error: Данные неполны: нет имени
|
||||
}
|
||||
```
|
||||
|
||||
## Проброс исключения
|
||||
Блок `catch` должен обрабатывать только те ошибки, которые ему известны, и «пробрасывать» все остальные.
|
||||
|
||||
Техника «проброс исключения» выглядит так:
|
||||
1. Блок `catch` получает все ошибки.
|
||||
2. В блоке `catch(err) {...}` мы анализируем объект ошибки `err`.
|
||||
3. Если мы не знаем как её обработать, тогда делаем `throw err`.
|
||||
|
||||
## Глобальный catch
|
||||
Давайте представим, что произошла фатальная ошибка (программная или что-то ещё ужасное) снаружи try..catch, и скрипт упал.
|
||||
|
||||
Существует ли способ отреагировать на такие ситуации? Мы можем захотеть залогировать ошибку, показать что-то пользователю (обычно они не видят сообщение об ошибке) и т.д.
|
||||
|
||||
В Node.js для этого есть process.on("uncaughtException"). А в браузере мы можем присвоить функцию специальному свойству window.onerror, которая будет вызвана в случае необработанной ошибки.
|
||||
```js
|
||||
window.onerror = function(message, url, line, col, error) {
|
||||
// ...
|
||||
};
|
||||
```
|
||||
- **message** - Сообщение об ошибке.
|
||||
- **url** - URL скрипта, в котором произошла ошибка.
|
||||
- **line**, col - Номера строки и столбца, в которых произошла ошибка.
|
||||
- **error** - Объект ошибки.
|
||||
11
docs/javascript/07-errors/02-extend-errors.md
Normal file
11
docs/javascript/07-errors/02-extend-errors.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Пользовательские ошибки, расширение Error
|
||||
Источник: [https://learn.javascript.ru/custom-errors](https://learn.javascript.ru/custom-errors)
|
||||
|
||||
- Мы можем наследовать свои классы ошибок от `Error` и других встроенных классов ошибок, но нужно позаботиться о свойстве name и не забыть вызвать `super`.
|
||||
- Мы можем использовать `instanceof` для проверки типа ошибок. Это также работает с наследованием. Но иногда у нас объект ошибки, возникшей в сторонней библиотеке, и нет простого способа получить класс. Тогда для проверки типа ошибки можно использовать свойство `name`.
|
||||
- Обёртывание исключений является распространённой техникой: функция ловит низкоуровневые исключения и создаёт одно «высокоуровневое» исключение вместо разных низкоуровневых. Иногда низкоуровневые исключения становятся свойствами этого объекта, как `err.cause` в примерах выше, но это не обязательно.
|
||||
|
||||
46
docs/javascript/08-promises/01-callbacks.md
Normal file
46
docs/javascript/08-promises/01-callbacks.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Введение: колбэки
|
||||
Источник *Deepseek*
|
||||
|
||||
Асинхронное программирование с использованием callback-функций в JavaScript — это один из традиционных подходов для работы с асинхронными операциями, такими как чтение файлов, запросы к серверу или таймеры. Callback-функция передается в качестве аргумента в асинхронную функцию и вызывается после завершения этой операции.
|
||||
|
||||
Вот пример асинхронного программирования с использованием callback:
|
||||
```js
|
||||
// Пример асинхронной функции, которая имитирует запрос к серверу
|
||||
function fetchData(callback) {
|
||||
// Имитируем задержку с помощью setTimeout
|
||||
setTimeout(() => {
|
||||
const data = { name: "John", age: 30 };
|
||||
// Вызываем callback-функцию и передаем ей данные
|
||||
callback(data);
|
||||
}, 2000); // Задержка 2 секунды
|
||||
}
|
||||
|
||||
// Callback-функция, которая будет вызвана после получения данных
|
||||
function handleData(data) {
|
||||
console.log("Данные получены:", data);
|
||||
}
|
||||
|
||||
// Вызов асинхронной функции с передачей callback
|
||||
fetchData(handleData);
|
||||
|
||||
console.log("Ожидание данных...");
|
||||
```
|
||||
|
||||
Объяснение:
|
||||
1. **fetchData** — это асинхронная функция, которая имитирует запрос к серверу с задержкой в 2 секунды.
|
||||
2. **callback** — это функция, которая передается в `fetchData` и будет вызвана после завершения асинхронной операции.
|
||||
3. **handleData** — это callback-функция, которая обрабатывает полученные данные.
|
||||
4. **setTimeout** используется для имитации задержки, как будто данные загружаются с сервера.
|
||||
|
||||
Вывод в консоль:
|
||||
```
|
||||
Ожидание данных...
|
||||
Данные получены: { name: "John", age: 30 }
|
||||
```
|
||||
Особенности:
|
||||
- Callback-функции могут привести к так называемому "callback hell" (ад колбэков), когда много асинхронных операций вложены друг в друга, что делает код сложным для чтения и поддержки.
|
||||
- В современных JavaScript-проектах вместо callback-функций часто используют Promises или async/await для более удобной работы с асинхронным кодом.
|
||||
85
docs/javascript/08-promises/02-promises.md
Normal file
85
docs/javascript/08-promises/02-promises.md
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Promises
|
||||
Источник *Deepseek*
|
||||
|
||||
Использование Promises (обещаний) в JavaScript — это более современный и удобный способ работы с асинхронными операциями по сравнению с callback-функциями. Promises позволяют избежать "callback hell" и делают код более читаемым и структурированным.
|
||||
|
||||
Вот пример асинхронного программирования с использованием Promises:
|
||||
```js
|
||||
// Пример асинхронной функции, которая возвращает Promise
|
||||
function fetchData() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Имитируем задержку с помощью setTimeout
|
||||
setTimeout(() => {
|
||||
const success = true; // Имитируем успешное выполнение или ошибку
|
||||
if (success) {
|
||||
const data = { name: "Alice", age: 25 };
|
||||
resolve(data); // Успешное выполнение
|
||||
} else {
|
||||
reject("Ошибка: Данные не получены"); // Ошибка
|
||||
}
|
||||
}, 2000); // Задержка 2 секунды
|
||||
});
|
||||
}
|
||||
|
||||
// Использование Promise
|
||||
fetchData()
|
||||
.then((data) => {
|
||||
console.log("Данные получены:", data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Запрос завершен.");
|
||||
});
|
||||
|
||||
console.log("Ожидание данных...");
|
||||
```
|
||||
Объяснение:
|
||||
1. **fetchData** — это функция, которая возвращает `Promise`. Внутри `Promise` выполняется асинхронная операция (в данном случае, с задержкой в 2 секунды).
|
||||
2. **resolve** — вызывается, если операция завершилась успешно. В этом случае `Promise` переходит в состояние "fulfilled" (выполнено), и данные передаются в метод .then().
|
||||
3. **reject** — вызывается, если произошла ошибка. В этом случае `Promise` переходит в состояние "rejected" (отклонено), и ошибка передается в метод .catch().
|
||||
4. **.then()** — обрабатывает успешный результат.
|
||||
5. **.catch()** — обрабатывает ошибки.
|
||||
6. **.finally()** — выполняется в любом случае, независимо от того, завершился `Promise` успешно или с ошибкой.
|
||||
|
||||
#### Вывод в консоль:
|
||||
```
|
||||
Ожидание данных...
|
||||
Данные получены: { name: "Alice", age: 25 }
|
||||
Запрос завершен.
|
||||
```
|
||||
#### Если произойдет ошибка:
|
||||
Если переменная `success` будет равна `false`, то вывод будет таким:
|
||||
```
|
||||
Ожидание данных...
|
||||
Ошибка: Данные не получены
|
||||
Запрос завершен.
|
||||
```
|
||||
#### Преимущества Promises:
|
||||
- Более читаемый и структурированный код.
|
||||
- Легко комбинировать несколько асинхронных операций с помощью `.then()`.
|
||||
- Удобная обработка ошибок через `.catch()`.
|
||||
|
||||
#### Пример с цепочкой Promises:
|
||||
```js
|
||||
fetchData()
|
||||
.then((data) => {
|
||||
console.log("Данные получены:", data);
|
||||
return data.age; // Возвращаем только возраст
|
||||
})
|
||||
.then((age) => {
|
||||
console.log("Возраст пользователя:", age);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
```
|
||||
Этот пример показывает, как можно последовательно обрабатывать данные с помощью цепочки `.then()`.
|
||||
|
||||
💥 **Thenable**
|
||||
> Если быть более точными, обработчик может возвращать не именно промис, а любой объект, содержащий метод .then, такие объекты называют «thenable», и этот объект будет обработан как промис.
|
||||
52
docs/javascript/08-promises/03-promises-error.md
Normal file
52
docs/javascript/08-promises/03-promises-error.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Обработка ошибок
|
||||
Источник: [https://learn.javascript.ru/promise-error-handling](https://learn.javascript.ru/promise-error-handling)
|
||||
|
||||
- `.catch` перехватывает все виды ошибок в промисах: будь то вызов `reject()` или ошибка, брошенная в обработчике при помощи `throw`.
|
||||
- `.then` также перехватывает ошибки таким же образом, если задан второй аргумент (который является обработчиком ошибок).
|
||||
- Необходимо размещать `.catch` там, где мы хотим обработать ошибки и знаем, как это сделать. Обработчик может проанализировать ошибку (могут быть полезны пользовательские классы ошибок) и пробросить её, если ничего не знает о ней (возможно, это программная ошибка).
|
||||
- Можно и совсем не использовать `.catch`, если нет нормального способа восстановиться после ошибки.
|
||||
- В любом случае нам следует использовать обработчик события `u`nhandledrejection` (для браузеров и аналог для других окружений), чтобы отслеживать необработанные ошибки и информировать о них пользователя (и, возможно, наш сервер), благодаря чему наше приложение никогда не будет «просто умирать».
|
||||
|
||||
## Неявный try…catch
|
||||
Вокруг функции промиса и обработчиков находится `«невидимый try..catch»`. Если происходит исключение, то оно перехватывается, и промис считается отклонённым с этой ошибкой.
|
||||
|
||||
«Невидимый try..catch» вокруг промиса автоматически перехватывает ошибку и превращает её в отклонённый промис.
|
||||
|
||||
Это работает не только в функции промиса, но и в обработчиках. Если мы бросим ошибку (throw) из обработчика (.then), то промис будет считаться отклонённым, и управление перейдёт к ближайшему обработчику ошибок.
|
||||
|
||||
## Пробрасывание ошибок
|
||||
Мы можем иметь столько обработчиков `.then`, сколько мы хотим, и затем использовать один `.catch` в конце, чтобы перехватить ошибки из всех обработчиков.
|
||||
|
||||
В обычном `try..catch` мы можем проанализировать ошибку и повторно пробросить дальше, если не можем её обработать. То же самое возможно для промисов.
|
||||
|
||||
Если мы пробросим `(throw)` ошибку внутри блока `.catch`, то управление перейдёт к следующему ближайшему обработчику ошибок. А если мы обработаем ошибку и завершим работу обработчика нормально, то продолжит работу ближайший успешный обработчик `.then`.
|
||||
|
||||
## Необработанные ошибки
|
||||
Что произойдёт, если ошибка не будет обработана? \
|
||||
В случае ошибки выполнение должно перейти к ближайшему обработчику ошибок.
|
||||
|
||||
Что происходит, когда обычная ошибка не перехвачена try..catch? Скрипт умирает с сообщением в консоли. Похожее происходит и в случае необработанной ошибки промиса.
|
||||
|
||||
JavaScript-движок отслеживает такие ситуации и генерирует в этом случае глобальную ошибку. Вы можете увидеть её в консоли, если запустите пример выше.
|
||||
|
||||
В браузере мы можем поймать такие ошибки, используя событие unhandledrejection:
|
||||
```js
|
||||
window.addEventListener('unhandledrejection', function(event) {
|
||||
// объект события имеет два специальных свойства:
|
||||
alert(event.promise); // [object Promise] - промис, который сгенерировал ошибку
|
||||
alert(event.reason); // Error: Ошибка! - объект ошибки, которая не была обработана
|
||||
});
|
||||
|
||||
new Promise(function() {
|
||||
throw new Error("Ошибка!");
|
||||
}); // нет обработчика ошибок
|
||||
```
|
||||
|
||||
Если происходит ошибка, и отсутствует её обработчик, то генерируется событие `unhandledrejection`, и соответствующий объект `event` содержит информацию об ошибке.
|
||||
|
||||
Обычно такие ошибки неустранимы, поэтому лучше всего – информировать пользователя о проблеме и, возможно, отправить информацию об ошибке на сервер.
|
||||
|
||||
18
docs/javascript/08-promises/04-promise-api.md
Normal file
18
docs/javascript/08-promises/04-promise-api.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Promise API
|
||||
Источник:
|
||||
В классе Promise есть 6 статических методов.
|
||||
|
||||
- **Promise.all(promises)** – ожидает выполнения всех промисов и возвращает массив с результатами. Если любой из указанных промисов вернёт ошибку, то результатом работы Promise.all будет эта ошибка, результаты остальных промисов будут игнорироваться.
|
||||
- **Promise.allSettled(promises)** (добавлен недавно) – ждёт, пока все промисы завершатся и возвращает их результаты в виде массива с объектами, у каждого объекта два свойства:
|
||||
- status: "fulfilled", если выполнен успешно или "rejected", если ошибка,
|
||||
- value – результат, если успешно или reason – ошибка, если нет.
|
||||
- **Promise.race(promises)** – ожидает первый выполненный промис, который становится его результатом, остальные игнорируются.
|
||||
- **Promise.any(promises)** (добавлен недавно) – ожидает первый успешно выполненный промис, который становится его результатом, остальные игнорируются. Если все переданные промисы отклонены, AggregateError становится ошибкой `Promise.any`.
|
||||
- **Promise.resolve(value)** – возвращает успешно выполнившийся промис с результатом value.
|
||||
- **Promise.reject(error)** – возвращает промис с ошибкой error.
|
||||
|
||||
Из всех перечисленных методов, самый часто используемый – **Promise.all**.
|
||||
41
docs/javascript/08-promises/05-promisification.md
Normal file
41
docs/javascript/08-promises/05-promisification.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Промисификация
|
||||
Источник: [https://learn.javascript.ru/promisify](https://learn.javascript.ru/promisify)
|
||||
|
||||
Промисификация – это длинное слово для простого преобразования. Мы берём функцию, которая принимает колбэк и меняем её, чтобы она вместо этого возвращала промис.
|
||||
|
||||
Такие преобразования часто необходимы в реальной жизни, так как многие функции и библиотеки основаны на колбэках, а использование промисов более удобно, поэтому есть смысл «промисифицировать» их.
|
||||
|
||||
💥 **На заметку:**
|
||||
- Промисификация – это отличный подход, особенно, если вы будете использовать async/await (см. следующую главу об Async/await) но она не является тотальной заменой любых колбэков.
|
||||
- Помните, промис может иметь только один результат, но колбэк технически может вызываться сколько угодно раз.
|
||||
- Поэтому промисификация используется для функций, которые вызывают колбэк только один раз. Последующие вызовы колбэка будут проигнорированы.
|
||||
|
||||
```js
|
||||
// promisify(f, true), чтобы получить массив результатов
|
||||
function promisify(f, manyArgs = false) {
|
||||
return function (...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
function callback(err, ...results) { // наш специальный колбэк для f
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
// делаем resolve для всех results колбэка, если задано manyArgs
|
||||
resolve(manyArgs ? results : results[0]);
|
||||
}
|
||||
}
|
||||
|
||||
args.push(callback);
|
||||
|
||||
f.call(this, ...args);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
// использование:
|
||||
f = promisify(f, true);
|
||||
f(...).then(arrayOfResults => ..., err => ...)
|
||||
```
|
||||
19
docs/javascript/08-promises/06-acync-await.md
Normal file
19
docs/javascript/08-promises/06-acync-await.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Async/await
|
||||
|
||||
По сути, это просто «синтаксический сахар» для получения результата промиса, более наглядный, чем `promise.then`.
|
||||
|
||||
Ключевое слово `async` перед объявлением функции:
|
||||
1. Обязывает её всегда возвращать промис.
|
||||
2. Позволяет использовать await в теле этой функции.
|
||||
|
||||
Ключевое слово `await` перед промисом заставит JavaScript дождаться его выполнения, после чего:
|
||||
1. Если промис завершается с ошибкой, будет сгенерировано исключение, как если бы на этом месте находилось `throw`.
|
||||
2. Иначе вернётся результат промиса.
|
||||
|
||||
Вместе они предоставляют отличный каркас для написания асинхронного кода. Такой код легко и писать, и читать.
|
||||
|
||||
Хотя при работе с `async/await` можно обходиться без `promise.then/catch`, иногда всё-таки приходится использовать эти методы (на верхнем уровне вложенности, например). Также `await` отлично работает в сочетании с `Promise.all`, если необходимо выполнить несколько задач параллельно.
|
||||
Reference in New Issue
Block a user